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;
}
Related
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
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);
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.
My question is, whether it is necessary to add #XmlElement before each element in your pojo to be picked up by jaxb, when making a JSON response. I am using jersey-json 1.17 . The reason I ask this is because, the example given on Jersey site does not use the annotation.
I get an out put as {}, but when I add #XmlElement before the attributes, I get the expected JSON output. Am I doing something wrong, because of which my JSON string is empty ?
My code :
The vertices list is populated in the constructor.
This produces the wrong output of {}
#XmlRootElement
public class SquareModel {
List<Float> vertices = new ArrayList<Float>();
....
}
Whereas this produces the a correct JSON string :
#XmlRootElement
public class SquareModel {
#XmlElement(name="vertices")
List<Float> vertices = new ArrayList<Float>();
....
}
My resource class which returns the JSON
#GET
#Produces(MediaType.APPLICATION_JSON)
public SquareModel getJsonString() {
return new SquareModel();
}
Thanks :)
No, by default a JAXB (JSR-22#) implementation will treat all public fields and properties (get/set combinations) as mapped (not requiring the #XmlElement annotation).
http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
If you wish to annotate a field I would recommend annotating your class with #XmlAccessorType(XmlAccessType.FIELD)
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
According to this http://jersey.java.net/nonav/documentation/latest/json.html#json.jaxb.approach.section
You should have this annotation (I'm also using it in my code, even though it XML oriented, but it gives me cool JSON also)
Taking this approach will save you a lot of time, if you want to
easily produce/consume both JSON and XML data format. Because even
then you will still be able to use a unified Java model. Another
advantage is simplicity of working with such a model, as JAXB
leverages annotated POJOs and these could be handled as simple Java
beans.
A disadvantage of JAXB based approach could be if you need to work
with a very specific JSON format. Then it could be difficult to find a
proper way to get such a format produced and consumed. This is a
reason why a lot of configuration options are provided, so that you
can control how things get serialized out and deserialized back.
Following is a very simple example of how a JAXB bean could look like.
Example 5.3. Simple JAXB bean implementation
#XmlRootElement
public class MyJaxbBean {
public String name;
public int age;
public MyJaxbBean() {} // JAXB needs this
public MyJaxbBean(String name, int age) {
this.name = name;
this.age = age;
}
}
So I have a class that I was planning on using for simple JSON serialization.
public class Thing {
private int field1;
private String some_other_field;
private List<SubType> subs;
private list<AnotherType> another;
public String toJson() {
Gson g = new Gson();
g.toJson(this);
}
}
So the documentation shows that if you want to serialize generic types, you need to specify a TypeToken:
Type listtype = new TypeToken<List<SubType>>() {}.getType();
gson.toJson(subs, listtype);
But then, how does this work if I have a whole class I want to serialize for? Where do I get to specify the serialization type for those two List<> types so that I can just pass the whole object in and get a serialized output? Is that even possible?
From the doc it seems that if you serialize a complete object with toJson(...), it deals with the generics attributes properly.
toJson(Object)
"Note that this method works fine if the any of the object fields are of generic type, just the object itself should not be of a generic type"
What output did you get with your object ?