I am using JAXB to serialize and deserialize java objects.
Classes are as:
public class Level1Class
{
String Id;
HashMap<String,Level2Class> level2Map = new HashMap<String,Level2Class>();
}
public class Level2Class
{
String Id;
}
I want to serialize and deserialize object of Level1Class.
Please suggest annotation for classes and fields.
What else do I need to include
1. default constructor
2. getter setter of fields
To make an object serializable, you just have to let it implement Serializable and make sure that every field of this object is serializable as well.
Related
While using jackson to deserialize and serialize a java DTO came across a weird behaviour.
Consider this sample java dto,
public class TempClz {
private List<String> field1;
public List<String> getField1() {
return field1;
}
public void setField1(List<String> field1) {
this.field1 = field1;
}
public List<String> getNotAtAll() {
return field1;
}
}
Now on creating a object of this class with field1 set to some value and on serializing this via a standard jackson mapper the sample json string obtained was
{"field1":["123"],"notAtAll":["123"]}
This behaviour was weird and I did not get a direct explanation for this in docs, but that once a getter is made, the property is available for both serialization and deserialization. This created a property using the function name in the resultant json response.
But again on deserialization of this string to pojo, the notAtAll list got appended to field1 list, i.e. in the resultant java object, field1 had size of two with values ["123","123"] which just seems wrong. Fixed this behaviour using jsonIgnore on the getter but can someone please help explain this behaviour exactly and whether this is intended?
A Getter Makes a Non-Public Field Serializable and Deserializable. So, no doubt that it added notAtAll field in json for getNotAtAll method. When you de-serialize the same string it has the values from both the getters but both of them return the same field i.e. field1. And consequently the values are added to your list. You've rightly used #JsonIgnore to ignore this getter.
There are several REST calls that require the same JSON entity with a different set of attributes. Example of the entity:
public class JsonEntity
{
public String id;
public String name;
public String type;
public String model;
}
JsonEntity is a part of the complex responses of different calls. The first call requires the whole JsonEntity without changes. Second call requires JsonEntity without type and model attributes. Thrid one requires JsonEntity without name attribute.
Is there any way to retrieve the same JSON entity with a particular set of attributes depending on the particular context (except separating JsonEntity) using Jackson?
I see 3 ways of doing this:
1. Use #JsonGetter
This annotation tells jackson to use a metho rather than a field for serialization.
Create 3 subclasses of JsonEntity, one for each response. Change JsonEntity and use #IgnoreField on every field, make them protected if possible. On each subclasses, create specific getter for the fields you need, example:
public class JsonEntitySecondCall extends JsonEntity
{
#JsonGetter("id")
public String getId(){
return id;
}
#JsonGetter("name")
public String getName(){
return name;
}
}
Also, create a clone/copy constructor for JsonEntity. For your second call, create a new JsonEntitySecondCall by cloning the original JsonEntity, and use it in your API. Because of the anotation, the created Object will only serialisze the given fields. I don't this you can just cast your object, because Jackson uses reflection.
2. Use #AnyGetter
the AnyGetter annotaiton allows you to define a map of what will be serialized:
private Map<String, Object> properties = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> properties() {
return properties;
}
Now you just need to tell your JsonEntity what properties it needs to return before each call (you could create 3 methods, one for each context, and use an enum to set which one must be used.).
3. Use #JsonInclude(Include.NON_NULL)
This annotation tells Jackson not to serialize a field if it is null. You can then clone your object and set null the fields you don't want to send. (this only works if you shouldn't send null elements to the API)
For more on Jackson annotations use this link.
I have a JSON String and I want to deserialize it to a Java object with a interface data member. The Java object looks like this:
public class Person {
private String id;
private String name;
private AddressInterface addr;
}
Both the Person and the AddressInterface are third party classes, so I can't make any changes to them.
When I used the following to deserialize the JSON string,
objectMapper.readValue(json_file, Person.class)
I got the following exception. It's because the object mapper doesn't know how to deserialize the AddressInterface field. Can someone let me know how to deserialize the string into an Person object in this case? Many Thanks.
abstract types either need to be mapped to
concrete types, have custom deserializer,
or be instantiated with additional type information
AddressInterface is an interface and is considered abstract. Both classes Foo and Bar could implement AddressInterface, but it would be unable to tell which one the data should be deserialized as.
Random idea which might work:
Put the interface in a wrapper. I'm just guessing since I don't know the library context, but maybe something like this. Also there's probably a few typos in here, but it shows the general idea.
public class AbstractSerializable<T> implements Deserialize {
private final String className;
private T obj;
public AbstractSerializable(T obj) {
this.obj = obj;
this.className = obj.getClass().getCardinalName();
}
#Override
public AbstractSerializable deserialize(ObjectMapper objectMapper) {
String clazz = input.readNext(String.class);
return objectMapper.readNext(Class.forName(clazz));
}
}
Edit: This would probably break if you tried to put a lambda in it.
Edit 2: #Hadi Note is correct that Gson would make some things easier, however it would run into the same issues. I did find this article which explains how to fix it when using Gson. It uses a similar approach to my answer, but they have a much better explanation.
With GSON library you can get rid of the boilerplate codes!
You can use GSON library in the link below!
https://www.tutorialspoint.com/gson/gson_quick_guide.htm
the problem is deserializing AddressInterface property because its an interface and I think objectMapper is trying to initilaize it's default constructer like bellow
addr = new AddressInterface();
you can create an empty concrete class which inherits the AddressInterface and use it instead of AddressInterface
public class Adress implements AddressInterface {
...
}
public class Person {
private String id;
private String name;
private Adress addr;
}
Well, I'm trying to parse objects and I'm having so much issues.
My classes are like this:
-Entidad-
public class Entidad{
private Long codEntidad;
private Set<Comunicacion> comunicacion;
/*------------ Getter and Setters --------------*/
}
-Comunicacion-
public class Comunicacion {
private Entidad entidad;
private Long codComunicacion;
/*------------ Getter and Setters --------------*/
}
I need to parse to DTO objects:
-EntidadDTO-
public class EntidadDTO{
private Long codEntidad;
private Set<ComunicacionDTO> comunicacionDto;
/*------------ Getter and Setters --------------*/
}
-ComunicacionDTO-
public class ComunicacionDTO {
private EntidadDto entidadDto;
private Long codComunicacion;
/*------------ Getter and Setters --------------*/
}
I tried to use:
BeanUtils.copyProperties(entidad, entidadDto);
It seems that the parse is success but the property entidadDto.getComunicacionDto(); is a hashMap of Comunicacion (not ComunicacionDTO)
Should I try to make a custom parse with reflection?
Also I'd like to use this to parse more objects with a similar structure.
Thanks!
Try dozer. You can define mappings from bean to bean using it.
http://dozer.sourceforge.net/
Why you want to parse java object and move data to other java object?
Parsing is for unstructured strings not for objects.
Use setters/getters to move data from one object to the other, using reflection will make you cry when you start doing refactorings.
I am working on conversion from JSON using Jackson 2, I work with application code that I cannot interfere into (Tacton Software). In there I have a class like that:
public class Quotation {
private Reference currency; // This type does not have deafult constructor
private List<QuotationItem> quotationItems = new ArrayList(); // In this there are abstract fields
// Getters, setters and other fields omitted for clarity
}
So basically I tried already to extend Quotation class like that:
class JSONQuotation extends Quotation{
#JsonSetter("currency")
public void notSetCurrency(JSONReference ref){
this.setCurrency(null);
}
#JsonSetter("items")
#Override
public void setItems (List<QuotationItem> item){
}
}
So there are two types of annotation I used:
Ignore setter for field I don't want to deserialize
Override setter
Anyway I'm still getting errors from ObjectMapper, of course, I had set MixIns
mapper.addMixIn(Quotation.class,JSONQuotation.class);
Anybody can help me with this or recommend some other deserializer ?