Exculde fields in json based on some condition - json

I have a list of objects of a class which I am rendering as json to the browser. Now there are certain attributes in the objects which I want to exclude from the json response if certain condition is not met.
So those attributes will be there for some objects of the list and will be absent for the other objects of that list.
How do I achieve that?
Mine is a spring boot application. Jackson is being used.
I am using Transformer for converting Entity to Bean and then ResponseEntity to convert the bean to json.
Please suggest possible solutions.
Thanks.

Make those values (which you want to be excluded) as null and then make use of the #JsonInclude annotation to suppress all null values.
#JsonInclude(Include.NON_NULL)
class Foo {
String bar;
}
you can exclude null values for specific fields too (As opposed to excluding null values for the entire object)
public class Foo {
private String field1;
private String field2;
#JsonInclude(Include.NON_NULL)
private String field3;
...
...
}
in version 2.x+ the syntax for this annotation is:
#JsonInclude(JsonSerialize.Inclusion.NON_NULL)
Or you can also set the global option:
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
In a Spring Project, objectMapper is the singleton instance of class ObjectMapper which you can either #Autowired or get from ApplicationContext

Related

JACKSON serialization of objects

I am new to JACKSON serialization, and writing Test cases for model classes.
So when i serialise an another object initialized in this model class following anomaly is seen::
Example::
class ToTest{
ABC abc;
//getter setter
}
class Test{
//everything that is needed
#Test
public void serialize() throws Exception{
ToTest toTest = new ToTest();
ABC abc = new ABC();
toTest.setABC(abc);
}
Now when I serilize this toTest object: the json string is missing the "ABC" class name. So i am not able to equalise them. Please help.
Jackson does not explicitly write out the class names when doing serialization do JSON. This is by design as the POJO objects used in serialization are intended for describing the contents of the JSON data, not necessarily preserving the class.
With that said, there are a few things you can do. If you want to preserve the original class, you can use annotations to add a class field, which might solve your issue. A quick search resulted in this as an example:
include class name in all objects serialized by jackson

Jackson mapper write id instead of entire object

I am using jackson 2.4.2 to mapp some hibernate results, because the hibernate object can be quite complex, the problem I am receiving is, I have a list of hibernate object, some of them may refer to the same object, thus jackson only mapp the object once, and all other objects are only mapped as an id. I don't want it behave like this and want it to write objects as object no matter if it is parse in other object or not.
Show us some code and especially your class structure and json/xml or whatever results.
But i think the problem is that you are only saving object_id as Integer and not as object.
Wrong:
public class Foo {
private String name;
private Integer foo_id;
}
Correct:
public class Foo {
private String name;
private Foo foo;
}

validating a JSON list as the root object with spring mvc

I need to validate a JSON list similar to the following:
[{"op":"A","path":"C","value":"B"},...]
in a Spring MVC application - I am currently deserializing (using default Jackson) to an object along the lines of:
public class Operations extends ArrayList<Operation>{}
public class Operation {
#NotEmpty
public String op;
#NotEmpty
public String path;
public Object value;
public void setOp(String op)... and other getters/setters
}
but I cannot figure out how to get jsr303 validation provided by reference hibernate implementation to fire for the attributes of Operation.
I can get it to function if I wrap the list in a class but then I have an incorrect format for the JSON, ie something like:
{"ops":[{"op":"A",...},...]}
is it possible to validate the first object (Operations)? and if not is it possible to serialize the first format (ie the JSON list) to an object of the second format (ie a list wrapped in a placeholder object with a placeholder field)
Update
Having failed to find a way to trigger the jsr303 validation on a bare ArrayList I have written a custom jackson json deserializer to stick it into a containing object with an annotated field along the lines of
#JsonDeserialize(using=OperationsDeserializer.class)
public class Operations {
#NotEmpty
private ArrayList<Operation> ops;
public void setOps(ArrayList<Operation>ops)...
public ArrayList<Operation> getOps()...
}
This works but now any autogenerated documentation for my api is generating json examples with the dummy "ops" field in it - ie {"ops" : [ ... ] }
so the search for a method of triggering jsr303 validation on an ArrayList that is not a field of another object continues - perhaps there is a way to inject a proxy wrapping class at runtime that might work around this?
Use ObjectMapper.class. it has a method which will convert Json Object into Class Object
method is , new ObjectMapper().readValue(String str, Class<T> valueType)
So you can iterate your Object array, convert to string and pass it to this method to get your result.
so it would look like,
new ObjectMapper().readValue(object.toString, Operation.class);

Serializing JPA entities to JSON using Jackson

Question regarding combination of Jackson/JPA
If there are about 20 entities in current application and I have add Jackson dependency in POM, does it mean all entities are by default ready to convert to JSON object? I saw a sample project seems only class annotated as #JsonIgnored is skipped by JSON. If so, then how can this happen, what is behind such mechanism? how JACKSON handle those entities which don't have any Jackson annotation, by default ignored or not? I've been looking for resources online but not much luck.
If only one of the 20 entities need to be mapped to JSON object, does it mean I have to add #JsonIgnore to all other 19 entities? If not, how Jackson differentiate with entity to work on?
Thanks.
Jackson and JPA don't have anything to do with each other. Jackson is a JSON parsing library and JPA is a persistence framework. Jackson can serialize almost any object - the only requirement being that the object have some kind of recognizable properties (Javabean type properties, or bare fields annotated with #JsonProperty. There is an additional requirement for deserialization, that the target type have a default (no-arg) constructor. So, for example, this is an object that Jackson can serialize:
// Class with a single Javabean property, "name"
class Person {
private String name;
public String getName() { return name ; }
public String setName(String name) { this.name = name ; }
}
And here is another:
// Class with a single field annotated with #JsonProperty
class Account {
#JsonProperty("accountNumber")
private String accountNumber;
}
And here is yet another:
#Entity
public class User {
#Id
private Long id;
#Basic
private String userName;
#Basic
#JsonIgnore
private String password;
#Basic
#JsonIgnore
private Address address;
// Constructors, getters, setters
}
The last example shows a JPA entity class - as far as Jackson is concerned it can be serialized just like any other type. But, take note of its fields: when this object is serialized into JSON two of the fields will not be included - 'password' and 'address'. This is because they have been annotated with #JsonIgnore. The #JsonIgnore annotation allows a developer to say 'Hey, its ok to serialize this object, but when you do so don't include these fields in the output'. This exclusion only occurs for the fields of this object, so for example, if you included an Address field in another class, but did not mark the field as ignorable, it would be serialized.
To prevent serialization of a type in all cases, regardless of context, use the #JsonIgnoreType annotation. When used on a type it basically means 'I dont care where this type is used, never serialize it'.
No, you don't need to add #JsonIgnore on every class and if you had tried you would have gotten a compile error, since you can't put it there. Jackson will only work on objects you give to it, it's no magic.
The Jackson documentation is easily found online, such at its project page on github or on the codehaus website.

Jackson passing null value to constructor

Considering a Java class constructor that take two parameters but allows the second to be null.
public class Category {
String name;
#JsonIgnore Category parent;
Category(String name,Category parent){this.name = name;this.parent=parent;}
}
I skipped the serialization of parent with #JsonIgnore annotation because I don't need it. Now Jackson is not capable to deserialize it because it don't find the parent property in the resulting Jason.
Is there any another solution but to define a constructor taking only the name parameter?
It is ok to have named constructor parameters that are missing -- you will simply get null instead of value. So you could just have:
#JsonCreator
public Category(#JsonProperty("name") String name, #JsonProperty("whatever") Category parent) { ... }
and whatever is found is passed. No exception will be thrown; Jackson never requires a property to exist. It just complains about things it does not recognize (unless configured not to).