Gson Custom deserializer - gson

I want to deserialize json string to java object. My class structure is this
public class Category {
String name;
int id;
ArrayList<Catalog> catalogs;
}
and catalog class structure is this
public class catalog {
private int catalogId = 0;
private String catalogName;
}
Following code i used to deserialize
Gson gson = new Gson();
ArrayList<Category> categories = gson.fromJson(jsonString, Category.class);
I got exception when it try to deserialize ArrayList catalogs;
If i remove ArrayList then it parse successfully
Thanks
Pawan

I solved this problem. The problem is that the string which i am parsing contain boolean value instead of Array . So There is exception while parsing.
The reason is that datatype is not match in json string which is parsed.
Thanks

Related

Spring boot - Deserialize enum by value lookup

I have the following enum:
public enum BusinessType {
C_CORP("C-Corporation"),
S_CORP("S-Corporation"),
// more types
public final String name;
BusinessType(String name) {
this.name = name;
}
}
The front end will submit the name property as a string (eg. C-Corporation), how can I get spring boot to deserialize / look up the correct enum? Currenty it tries to look up the actual string on the enum, giving the error:
No enum constant ai.interval.common.model.enums.BusinessType.C-Corporation
This is the property I have in the view received from the front end:
BusinessType getBusinessType();
Thanks
Build a getter for your fields, then add the #JsonValue annotation to your getter.
public enum BusinessType {
...
#JsonValue
public String getName() {
return name;
}
}
You can find other options in section 4 of this link: How To Serialize and Deserialize Enums with Jackson

Java Jackson writeAsString conversion

using Java8 with jackson
I have code convert A class into json String, which works fine, i have Scenario where if i want values of rate1 and rate2 to be blank string if certain values.
I am wondering if there is quick and easy way to do it ?
#JsonAutoDetect(fieldVisiblity=ANY)
class A{
UUID id;
CustomEnumType type;
BigDecimal value;
BigDecimal rate1
BigDecimal rate2;
}
A a = new A();
// a filled up with values
string jsonStr = objectMapper.writeValueAsString(a);
I tried using custom Seralizer class as following but not sure how do i convert UUID string representation ?
public class ASerializer extends StdSerializer<A>{
... ASerializer()..
#Override
public void serialize(A value, JsonGenerator g, SerializerProvider p){
g.writeStratObject();
// how do i convert UUID to string ?
g.writeEndObject();
}
}
Just call toString, UUID has static fromString method to deserialize.

Spring-Mongo : mapping mongo document field/s to BasicDBObject/Map of BasicDBObject of an Entity

I have an entity ProjectCycle mapped to mongo DB collection ProjectCycle. I am trying to retrieve 2 fields, _id and Status. I am able to retrieve both like the following
#Document(collection="ProjectCycle")
public class ProjectCycle {
#Id
private String id;
#Field("Status")
private String status;
//getters and setters
}
Application.java
Query query = new Query();
query.fields().include("Status");
Criteria criteria = new Criteria();
criteria.and("_id").is("1000");
query.addCriteria(criteria);
Iterable<ProjectCycle> objectList = mongoOperations.find(query, ProjectCycle.class);
for(ProjectCycle obj : objectList) {
System.out.println("_id "+obj.getId());
System.out.println("status "+obj.getStatus());
}
Output
_id 1000
status Approved
But, the problem is when i use an Entity with field private DBObject basicDbObject; instead of private String status; i am getting value as null instead of Approved
I have tried like the following
public class ProjectCycle {
#Id
private String id;
private DBObject basicDbObject;
//getter & setter
}
What I am trying to achieve is that, the collection 'ProjectCycle' is very large and creating a POJO corresponding to it is quiet difficult. Also I am only reading data from mongoDB. So creating the entire POJO is time wasting and tedious.
How I can achieve mapping between any field/fields from mongo Collection to entity?.
Will it be possible to create a Map<String, BasicDBObject> objectMap; to fields returned from query? I am using Spring-data-mongodb for the same.
Version details
Spring 4.0.7.RELEASE
spring-data-mongodb 1.7.2.RELEASE
Try mapping your query like below.
Iterable<BasicDBObject> objectList = mongoOperations.find(query, BasicDBObject.class, collectionname);
for(BasicDBObject obj : objectList) {
System.out.println("_id "+obj.get("id"));
System.out.println("status "+obj.get("status"));
}

How to parse Dynamic lists with Gson annotations?

I am using Retrofit and Gson to query an API, however I have never come across a JSON response like it.
The Response:
{
Response: {
"Black":[
{"id":"123","code":"RX766"},
{"id":"324","code":"RT344"}],
"Green":[
{"id":"3532","code":"RT983"},
{"id":"242","code":"RL982"}],
"Blue":[
{"id":"453","code":"RY676"},
{"id":"134","code":"R67HJH"}]
}
}
The problem is the list elements id eg "black" is dynamic, so I a have no idea what they will be.
So far I have created a class for the inner type;
class Type {
#SerializedName("id") private String id;
#SerializedName("code") private String code;
}
Is it possible to have the following?
class Response {
#SerializedName("response")
List<Type> types;
}
And then move the list ID into the type, so the Type class would become;
class Type {
#SerializedName("id") private String id;
#SerializedName("code") private String code;
#SerializedName("$") private String type; //not sure how this would be populated
}
If not, how else could this be parsed with just Gson attributes?
Ok so I have just seen this question;
How to parse dynamic JSON fields with GSON?
which looks great, is it possible to wrap a generic map with the response object?
If the keys are dynamic you want a map.
class Response {
#SerializedName("response")
Map<String, List<Type>> types;
}
After deserialization you can coerce the types into something more semantic in your domain.
If this is not suitable you will need to register a TypeAdapter or a JsonDeserializer and do custom deserialization of the map-like data into a simple List.

Use a custom deserializer only on fields?

I do a replication mechanism where I synchronize two databases. For communicating between databases I serialize the objects into JSON using Gson. Each object has a UUID to identify it. To avoid having to send the items that are up to date I use the objects UUID when an object is included in a field in an object to be replicated.
We got the following classes:
public class Entity {
String uuid;
// Getters and setters..
}
public class Article extends Entity {
String name;
Brand brand;
// Getters and setters..
}
public class Brand extens Entity {
String name;
Producer producer
// Getters and setters..
}
public class Producer extends Entity {
String name;
// Getters and setters..
}
If I serialize Article its JSON representation will look like this:
{"brand":"BrandÖ179d7798-aa63-4dd2-8ff6-885534f99e77","uuid":"5dbce9aa-4129-41b6-a8e5-d3c030279e82","name":"Sun-Maid"}
where "BrandÖ179d7798-aa63-4dd2-8ff6-885534f99e77" is the class ("Brand") and the UUID.
If I serialize Brand I expect:
{"producer":"ProducerÖ173d7798-aa63-4dd2-8ff6-885534f84732","uuid":"5dbce9aa-4129-41b6-a8e5-d3c0302w34w2","name":"Carro"}
In Jackson I would change Article class to:
public class Article {
String uuid;
String name;
#JsonDeserialize (using = EntityUUIDDeserializer.class) # JsonSerialize (using = EntityUUIDSerializer.class)
Brand brand;
// Getters and setters..
}
and implement custom serializer and deserializer to return the UUID instead of the object.
Gson do not have a #JsonDeserialize annotation.
If we install the serializer and deserializer doing like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Producer.class, new EntityUUIDDeserializer())
.registerTypeAdapter(Brand.class, new EntityUUIDDeserializer())
.registerTypeAdapter/Producer.class, new EntityUUIDSerializer())
.registerTypeAdapter(Brand.class, new EntityUUIDSerializer())
.create();
We can serialize Article and Brand ok.
Deserialize Article by
Article article= gson.fromJson(inputJSONString, Article.class);
works fine but
Brand brand= gson.fromJson(inputJSONString, Brand.class);
do not work. I guess the probem is that when we deserialize a Brand we get the deserializer for Brand to kick in trying to return an UUID string, but we want the deserializer to return a Brand-object instead.
Is there a way to avoid creating two different Gson objects? The problem with two diffrent Gson objects is when you want to deserialize an object that contains both Article and Brand.
You write the serializer/deserializer and register it with Gson (using the GsonBuilder).
https://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserialization
Gson g = new GsonBuilder()
.registerTypeAdapter(Producer.class, new MyProducerDeserializer())
.registerTypeAdapter(Producer.class, new MyProducerSerializer())
.create();
When you serialize/deserialize your Brand class, it will use them for the Producer field contained therein.

Resources