I have the following classes -
Employee
public class Employee {
private String firstName ;
private String lastName ;
private String emailAddress ;
private String ssn ;
}
Payroll
public class Payroll {
// different payroll related fields
private Employee emp ;
}
HR
public class HR {
// different HR related fields
private Employee emp ;
}
Now when I serialize my Payroll class, I don't want to serialize my ssn field from Employee class.
Where as when I serialize my HR class, I don't want to serialize my emailAddress field from Employee class.
How I can dynamically exclude fields from serializing by using Jackson JSON API?
How I can dynamically exclude fields from serializing by using Jackson JSON API?
This seems like a prime candidate for applying JacksonJsonViews.
public class Employee {
private String firstName;
private String lastName;
#JsonView(Views.Payroll.class) private String emailAddress;
#JsonView(Views.HR.class) private String ssn;
}
public class Payroll {
// snip
#JsonView(Views.Payroll.class)
private Employee emp;
}
public class HR {
// snip
#JsonView(Views.HR.class)
private Employee emp;
}
You can achieve this with the help of a JsonFilter.
Annotate the class you want to filter as thus:
#JsonFilter("employeeFilter")
public class Employee {
private String firstName ;
private String lastName ;
private String emailAddress ;
private String ssn ;
}
Create a service called FilterBeanService(Or anything really)
#Service
public class FilterBeanService {
// fields is an array of field names you wish not to sned in your response
// beanFilterName is value you give when you annotage your bean class
// dataSet is the data you want to filter
public static MappingJacksonValue filterBean(String[] fields, String beanFilterName, Object dataSet ) {
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept(fields);
FilterProvider filterProvider = new SimpleFilterProvider().addFilter(beanFilterName, filter);
MappingJacksonValue jacksonValue = new MappingJacksonValue(dataSet);
jacksonValue.setFilters(filterProvider);
return jacksonValue;
}
}
In your controller, you can then filter fileds you do not want
#GetMapping("/whatever")
public ResponseEntity<MappingJacksonValue> getSomething(){
List<Employee> employees = eventRepo.findAll();
String[] fields = {"ssn"};
MappingJacksonValue jacksonValue = FilterBeanService.filterBean(fields, "employeeFilter", employees);
return jacksonValue;
}
I answered below to dynamically deserialise with customer reader. Can do similar thing with writer to ignore when serialising.
Jackson Change JsonIgnore Dynamically
Related
{
"cust":"A",
"del":[{
"type1": "id",
"type2":[{
"name":"address"
}]
}]
I have converted this json to below model class
public class Del{
public String type1;
public JSONArray type2; // "type2" has dynamic key and value which are string, it can have "name":"address","id":"sal" pair etc dynamically
}
public class Root{
public String cust;
public List<Del> del;
}
But, this mapping is showing error. how to fetch key and value inside "type2" in dynamic way where attribute names are not fixed.
If you have a list, you need a List<T>. What is T? If it can have any number of keys, then it must be a Map<K, V>. K is String, and V is either String or Object, depending on your actual structure. If you have a handful of expected keys and want to ignore everything else, make T a custom class of yours:
class Type2Props {
public String name;
public String address;
public String id;
public String sal;
}
Properties/fields without a value in the JSON will be left initialized as null.
Putting it together, you either need
public class Del {
public String type1;
public List<Type2Props> type2;
}
or
public class Del {
public String type1;
public List<Map<String, String>> type2; /* might be `Map<String, Object>` */
}
So I have passed data in ajax as:
{
“name” : “Rahul”,
“age” : “23”,
“information” : [
{
“id” : “901”,
“role” : “developer”
}
],
“salary” : “21000”,
}
For this I have created two DTO classes as
class EmployeeDTO {
#SerializedName(“name”)
private String name;
#SerializedName(“age”)
private String age;
#SerializedName(“information”)
private List<InformationDTO> informationDto;
#SerializedName(“Salary”)
private String salary;
//Their getters and setters
}
I mentioned List because I took information as an array of objects. Then I have another DTO class
class InformationDTO {
#SerializedName(“id”)
private String id;
#SerializedName(“role”)
private String role;
}
Now in my Sling Servlet I am trying to get values of information array like
String information = request.getParameter(“information”);
But I am getting null value. How can I store this array information in my DTO class Employee using InformationDTO?
How to save array of objects into DTO class using sling servlet?
In my controller I have the following method:
#RequestMapping(value = "/getAll", method = RequestMethod.GET)
public List<Topic> getAllTopics() {
List<Topic> allTopics = service.getAllTopics();
assert allTopics.size() > 0; // is not empty
System.out.println(allTopics.get(0)); // Topic{id=1, name='bla', description='blahhh'}
return allTopics;
}
When I go to http://localhost:8080/getAll I get [{},{},{},{}] as a result but service.getAllTopics() returns non empty List So the list to be send is not empty but the browser receives invalid JSON. However, there is no problem in serializing objects since the following method return valid JSON. What's the problem?
#GetMapping("/json")
public List<Locale> getLocales() {
return Arrays.asList(DateFormat.getAvailableLocales());
}
I'm running latest Spring Boot, i.e. 2.1.3.RELEASE.
Update
Here's my entity class - Topic
#Entity
#Table(name = "topic", schema="tetra")
public class Topic {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String description;
public Topic() {
}
public Topic(String name, String description) {
this.name = name;
this.description = description;
}
#Override
public String toString() {
return "Topic{" +
"id=" + id +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}
By default , Jackson will only serialise the public fields and public getters into JSON. As the Topic neither have public fields nor the public getter , nothing will be serialised and you get an empty JSON object.
There are plenty of ways to configure it such as:
(1) Simply add public getter for all fields
(2) Use #JsonAutoDetect(fieldVisibility = Visibility.ANY) such that private fields can also be auto detected :
#Entity
#Table(name = "topic", schema="tetra")
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class Topic {
}
(3) Use #JsonProperty to explicitly pick what fields/getter to be serialised .The nice things of this approach is that the field name in JSON can be different from the POJO :
#Entity
#Table(name = "topic", schema="tetra")
public class Topic {
#JsonProperty("id")
private Integer id;
#JsonProperty("name")
private String name;
#JsonProperty("description")
private String description;
}
I have two classes:
public class Team {
private Long id;
private String name;
...
}
public class Event {
private Long id;
#ManyToOne
private Team homeTeam;
#ManyToOne
private Team guestTeam;
...
}
Controller:
public #ResponseBody List<Event> getAll() {...
}
Now I have Json:
[{"id":1,"homeTeam":{"id":2,"name":"Golden State"},"guestTeam":{"id":1,"name":"Philadelphia"},...
What I want:
[{"id":1,"homeTeam":"Golden State","guestTeam":"Philadelphia",...
How I can point Jackson to output only name of Team instead of full Object?
Benoit's answer will not generate JSON of the desired form, it would produce something like this:
[{"id":1,"homeTeam":{"name":"Golden State"},"guestTeam":{"name":"Philadelphia"},...
Instead what you want to do is make your Team class look something like this:
public class Team {
private Long id;
private String name;
public Long getId() {
return id;
}
#JsonValue
public String getName() {
return name;
}
...
}
This will produce the desired JSON:
[{"id":1,"homeTeam":"Golden State","guestTeam":"Philadelphia",...
But may require additional handling for deserialization.
Exclude all properties of the Team object except the name using : #JsonIgnoreProperties
#JsonIgnoreProperties
public String getPropertyToExclude() {
return propertyToExclude;
}
So that Jackson will serialize only the Team name in the JSON.
I use DataContractJsonSerializer to deserialize json data in Silverlight 4.
Json data key names do not match my class property names; so I guess I have to use
DataMemberAttribute. So I did the following:
[DataContract]
public class Person : Model
{
[DataMember(Name = "id")]
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
[DataMember(Name = "name")]
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
Now deserialization fails because I didn't apply DataContractAttribute to Person's base class Model. Is it a strict requirement? Also, after I applied DataContractAttribute to Model, deserialization fails again, because I applied DataMember attributes to private fields, not to the public properties. Why can't I apply them to private members (the documentation seems to say otherwise).
NOTE: server-side code is not ASP.NET; so WCF isn't used.
In order to get the private members to serialize over WCF correctly, we had to change them all to protected internal instead of private. Maybe the same applies for DataContractJsonSerializer?