Genson 1.4 (JSON) not processing inherited Pojo's - java

I am using genson 1.4 for JSON processing in my REST implementation , JSON Inheritance is not working while using genson .please find the sample code structure below.
This is my BaseObject
This is my BaseObject
public class SynBaseObject implements Serializable
{
private Long status;
//GettersAndSetters
}
This is my Child Class
public class PhoneNumber extends SynBaseObject
{
private String countryCode;
private String areaCode;
private String localNumber;
//GettersAndSetters
}
This is my Response Object
public class ResponseObject implements Serializable
{
private Integer errorCode;
private String errorMessage;
private Long primaryKey;
private SynBaseObject baseClass;
public ResponseObject()
{
}
public SynBaseObject getBaseObject()
{
return baseClass;
}
public void setBaseObject(SynBaseObject baseClass)
{
this.baseClass = baseClass;
}
public Integer getErrorCode()
{
return errorCode;
}
public void setErrorCode(Integer errorCode)
{
this.errorCode = errorCode;
}
}
This is the GENSON JSON Output:
{"baseObject":{"status":null},"errorCode":null,"errorMessage":null,"primaryKey":null}
CountryCode,areaCode and localNumber is missing in JSON,only the base class is processed .Tried the same from code like this
Genson genson = new Genson();
PhoneNumber number = new PhoneNumber();
number.setCountryCode("2");
number.setAreaCode("3");
number.setLocalNumber("9645");
ResponseObject responseObject = new ResponseObject();
responseObject.setBaseObject(number);
String serialize = genson.serialize(responseObject);
System.out.println(serialize);
Output was the same like in the rest service.

By default Genson uses the static type during ser/de. Meaning here it will see the object as an instance of SynBaseObject and not of the concrete type PhoneNumber.
You can tell Genson to use the runtime type via configuration:
Genson genson = new GensonBuilder().useRuntimeType(true).create();
Here you can find some examples on how to customize Genson with Jaxrs.
Note that if you ever want to deserialize to a ResponseObject, then you will probably have troubles as in the json there is no information about what is the concrete type of base object. However if the consumed json is also produced by Genson you can easily solve this problem by enabling class metadata serialization builder.useClassMetadata(true).
Some more documentation about the handling of polymorphic types in Genson.

Related

Jackson process string if annotated

If the field has an annotation, I need to replace all the & characters in the string with § when deserializing, and do the opposite when serializing
For example i created an annotation and marked a field with it
public class SomeData {
#MinecraftColorText
private String str;
}
I need read this json:
{"str":"&6Some nice text"}
and in java object str field need be: §6Some nice text
Im need process only annotated fields, not all String
I wanted to do it with ContextualSerializer, but as I understand it, it replaces the standard serialization
So you should change your custom annotation #MinecraftColorText and add serialize and deserialize convertors:
#JsonDeserialize(converter = MinecraftDeserializeConverter.class)
#JsonSerialize(converter = MinecraftSerializeConverter.class)
#Retention(RUNTIME)
#Target(FIELD)
#JacksonAnnotationsInside
public #interface MinecraftColorText {
}
Deserialize converter:
public class MinecraftDeserializeConverter extends StdConverter<String, String> {
#Override
public String convert(final String s) {
return s.replaceAll("&", "§");
}
}
Serialize converter:
public class MinecraftSerializeConverter extends StdConverter<String, String> {
#Override
public String convert(final String s) {
return s.replaceAll("§", "&");
}
}
and just use:
#MinecraftColorText
private String str;
p.s: Don't forget about #JacksonAnnotationsInside that notify jackson about your custom serialization action.
See more here

How to rename json object name with java annotation?

How to rename json object name with java annotation?
Object structure in java:
public class ParentClass {
private MyClass myClass;
}
public class MyClass {
private String name;
}
Json will have next view:
{
"myClass":{
"name":"value"
}
}
How can I change name of "myClass" using java/spring annotations, something like
#JsonObjectName("abc")
public class MyClass {
private String name;
}
and json will look like:
{
"abc":{
"name":"value"
}
}
Rename the variable:
private MyClass myClass;
To:
private MyClass abc;
This will yield the correct JSON-output without the use of annotations.
If you still want to use annotations and keep the name of the variable you can use #JsonProperty():
#JsonProperty("abc") // name of the property
private MyClass myClass;
#SerializedName("abc") is also possoble
It depends on the framework you are using. If you are using Jackson Library you can use:
public class ParentClass {
private MyClass myClass;
}
#JsonProperty("abc")
public class MyClass {
private String name;
}
If you are using Gson then
#SerializedName(value = "abc")
public class MyClass {
private String name;
}
Additionally in Gson if you want to use any alternate name for the field during deserialization we can use alternate as below:
#SerializedName(value = "abc", alternate ="xyz")
public class MyClass {
private String name;
}
alternate is to be used only at time of deserialization and GSON will only process/deserialize the last occurence of that field from JSON data.

How to deserialize a generic object at runtime with Jackson

Say I have the following java classes (getters & setters omitted for brevity).
public class AllMyEvents {
private List<SomeEvent<?>> eventList;
}
public class SomeEvent<T> {
private long time;
#JsonProperty("event_type")
private String eventType;
#JsonProperty("event_data")
private T eventData;
}
public class BigEvent {
private List<SomeEvent<LittleEvent>> subEvents;
}
public class LittleEvent {
private long data;
}
When I call:
ObjectMapper om = new ObjectMapper();
AllMyEvents events = om.readValue(IOUtils.toString(jsonData, "UTF-8"),AllMyEvents.class);
The field eventData is of type LinkedHashMap. What I want is for this fields type to be specified by the eventType string. If the string is 'big' I want eventData to have type BigEvent or LittleEvent if the string is 'little'.
Is it possible to do this with Jackson annotations, or will I need to write a custom serializer/deserializer, or some other method? I'm using Jackson 1.9 if that is relevant.
Json Sub types is your answer.
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="#class")
#JsonSubTypes({
#JsonSubTypes.Type(value=BigEvent.class, name="big"),
#JsonSubTypes.Type(value=LittleEvent.class, name="little")
})
public class SomeEvent<T> {
private long time;
#JsonProperty("event_type")
private String eventType;
...
Also see: http://wiki.fasterxml.com/JacksonPolymorphicDeserialization

How to deserialize JSON Array contained an abstract class without modifying a parent class?

I'm trying to deserialize JSON Array, which is persisted into my MongoDB, to a Java object by using Jackson. I found many tutorials mentioned to handle this polymorphism by adding:
#JsonTypeInfo(use=Id.CLASS,property="_class")
to a Super-class. However, in my case, I can't be able to modify the Super-class. So, are there some solutions to solve it without modifying the Super-class? Here is my code:
public class User {
#JsonProperty("_id")
private String id;
private List<Identity> identities; // <-- My List contains objects of an abstract class; Identity
public User(){
identities = new ArrayList<Identity>();
}
public static Iterable<User> findAllUsers(){
return users().find().as(User.class); // Always give me the errors
}
/*More code*/
}
It always give me the error - Can not construct instance of securesocial.core.Identity, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information.
You can use #JsonDeserilize annotation to bind a concrete implementation class to an abstract class. If you cannot modify your abstract class you can use the Jackson Mix-in annotations to tell Jackson how to find the implementation class.
Here is an example:
public class JacksonAbstract {
public static class User {
private final String id;
private final List<Identity> identities;
#JsonCreator
public User(#JsonProperty("_id") String id, #JsonProperty("identities") List<Identity> identities) {
this.id = id;
this.identities = identities;
}
#JsonProperty("_id")
public String getId() {
return id;
}
public List<Identity> getIdentities() {
return identities;
}
}
public static abstract class Identity {
public abstract String getField();
}
#JsonDeserialize(as = IdentityImpl.class)
public static abstract class IdentityMixIn {
}
public static class IdentityImpl extends Identity {
private final String field;
public IdentityImpl(#JsonProperty("field") String field) {
this.field = field;
}
#Override
public String getField() {
return field;
}
}
public static void main(String[] args) throws IOException {
User u = new User("myId", Collections.<Identity>singletonList(new IdentityImpl("myField")));
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Identity.class, IdentityMixIn.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(u);
System.out.println(json);
System.out.println(mapper.readValue(json, User.class));
}
}

Best way to map json to a Java object

I'm using restTemplate to make a rquest to a servlet that returns a very simple representation of an object in json.
{
"id":"SomeID"
"name":"SomeName"
}
And I have a DTO with those 2 fields and the corresponding setters and getters.
What I would like to know is how to create the object using that json response
without having to "parse" the response.
Personally I would recommend Jackson. Its fairly lightweight, very fast and requires very little configuration. Here's an example of deserializing:
#XmlRootElement
public class MyBean {
private String id;
private String name;
public MyBean() {
super();
}
// Getters/Setters
}
String json = "...";
MyBean bean = new ObjectMapper().readValue(json, MyBean.class);
Here's an example using Google Gson.
public class MyObject {
private String id;
private String name;
// Getters
public String getId() { return id; }
public String getName() { return name; }
}
And to access it:
MyObject obj = new Gson().fromJson(jsonString, MyObject.class);
System.out.println("ID: " +obj.getId());
System.out.println("Name: " +obj.getName());
As far as the best way, well that's subjective. This is one way you can accomplish what you need.
http://code.google.com/p/json-simple/ is nice and lightweight for this

Categories