How can I serialize and deserialize this object with gson to json:
public class test{
#Expose
public List< Pair<Double,Double> > list;
#Expose
public int alpha;
}
I've tried this:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String str = gson.toJson(testInstance,test.class);
where testInstance is an instance of class test, but it's not working because of Pair structure in List.
You have configured Gson object using excludeFieldsWithoutExposeAnnotation method.
From documentation:
Configures Gson to exclude all fields from consideration for
serialization or deserialization that do not have the Expose
annotation.
Could you change Pair class? If yes, you have to add #Expose annotation to each property which you want serialize to JSON. If no, you can create similar class in your program and add annotations.
if the object is of a generic type, then the Generic type information is lost because of Java Type Erasure. You can solve this problem by specifying the correct parameterized type for your generic type.
Try parameterized type like List<String>. This should work
Related
This question has been asked multiple time, I have a Java POJO class which I would like to serialize by excluding some attributes. In order to do this, I am using #Expose from GSON. The problem is that it does not seem to work.
Even if I use this: Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
It does not work.
I am reluctant to use transient because it disables both serialization and deserialization of the given attribute.
you can use transient
private transient String property;
Make sure you initialize your Gson object properly. You should call excludeFieldsWithoutExposeAnnotation method in your GsonBuilder if you want to use the Exclude annotation.
For example
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Gson javadoc description of excludeFieldsWithoutExposeAnnotation
I'm working on an app that is using Gson as JSON deserializer and needs to deserialize polymorphic JSON from REST API. Before explaining mi issue note that I've already been looking around polymorphic deserialization with Gson and have implemented it on several cases successfully. So this is a specific issue I'm having. Also I've read this great post and this Stack Overflow discussion before asking this. I'm using RuntimeTypeAdapterFactory to deserialize polymorphic objects by the way.
The problem I'm having is that apparently GSON's RuntimeTypeAdapterFactory does't allow to declare the field which specifies the type of the object inside the hierarchy structure. I'll explain further with some code. I have the following pojos structure (pojos had been reduced for the sake of simplicity):
public abstract class BaseUser {
#Expose
protected EnumMobileUserType userType;
}
public class User extends BaseUser {
#Expose
private String name;
#Expose
private String email;
}
public class RegularUser extends User {
#Expose
private String address;
}
public class SpecialUser extends User {
#Expose
private String promoCode;
}
Now this is the code where I defined the RuntimeTypeAdapterFactory for User hierarchy.
public static RuntimeTypeAdapterFactory<BaseUser> getUserTypeAdapter() {
return RuntimeTypeAdapterFactory
.of(BaseUser.class, "userType")
.registerSubtype(User.class, EnumMobileUserType.USER.toString())
.registerSubtype(RegularUser.class, EnumMobileUserType.REGULAR.toString())
.registerSubtype(SpecialUser.class, EnumMobileUserType.SPECIAL.toString());
}
public static Gson getGsonWithTypeAdapters() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapterFactory(getUserTypeAdapter());
return builder.create();
}
Now when I try to deserialize a JSON text:
{
"user":{
"userType":"USER",
"email":"albert#gmail.com",
"name":"Albert"
}
}
I get this exception:
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType
But if I change the name of the property "userType" in my BaseUser class to "type" for example and I deserialize the same JSON everything works properly. I don't get why Gson RuntimeTypeAdapterFactory has this restriction. In fact in this blog post apparently this is not an issue.
Can anyone explain what's going on here, why the name of the property that defines the type cannot be defined inside the pojos hierarchy?
EDIT the issue is not when deserializing but when serializing using the code described above. Find further explanation in the answer.
Well, after some time digging I found out that the problem is not actually deserializing, the problem comes when serializing and having a RuntimeTypeFactory registered as described in the question. If you register a runtimeTypeAdapterFactory and use the same field name to define the class type in the factory and in your pojo, json resulting from serializing pojo to json using GSON with the RuntimeTypeAdapterFactory for a SpecialUser for example will be:
{
"user":{
"userType":"SPECIAL",
"email":"albert#gmail.com",
"name":"Albert"
"userType":"SPECIAL"
}
}
This will result in the exception described:
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType
because de field userType is repeated in the json due to GSON serializer, which will automatically add a field as declared in the RuntimeTypeAdapterFactory registered for the class BaseUser.
I think that using your own userType without #Expose annotation will do the trick
Regads
You can always use a default Gson instance to serialize (new Gson()) and then use the RuntimeTypeAdapterFactory instance to deserialize.
It is recommended not to use #Expose if you want everything to be transformed. It only blows up your model classes with redundant annotations.
Is there away to parse json with java keywords like class, case, default etc. to java object using Gson library?
The lines
Gson gson = new Gson();
MyObject myObject = gson.fromJson(json, MyObject.class);
simply parse json to my pojo, but I have key "class" in my json and I can't use the field "class" in java classes.
Yes, annotate your fields with #SerializedName, specifying the name of the field.
#SerializedName("class")
private String classField;
Or use a custom TypeAdapter.
You have to use annotations. These annotations tell Gson which JSON field maps to which Java property:
http://www.javacreed.com/gson-annotations-example/
Working Java, using Gson. The input starts:
{"success":1,"return":{
Unfortunately, as you know, you can not create a field/variable named 'return' in Java. So, how does one get around this, as the bulk of the data is behind the 'return' field?
This question Serialize JSON object named "return" is related, but the language is C#.
You could use a different name for your field using gson's Field Naming Support
public class Whatever {
private int success;
#SerializedName("return")
private OtherType returnValue;
...
}
Annotate your field with
#SerializedName("return")
private SomeType doesntMatter;
Gson will use the value given to the #SerializedName annotation to map your field by name.
You can use Java annotations of Gson #SerializedName("return").
#SerializedName("return")
private String returnField;
About Gson annotations you can read here.
I am trying to deserialize a JSON object to a Java object using jackson. The json was created using the jackson library itself by another developer and is provided to me. The Object graph has a variable of Type guava's ImmutableMap which is an abstract class.Hence jackson throws me the following exception when I try to deSerialize. I am not the owner of the myJava class and hence couldn't make any changes to it like changing the type or adding annotations by writing a custom deserializer.
org.codehaus.jackson.map.JsonMappingException: Can not find a
deserializer for non-concrete Map type [map type; class
com.google.common.collect.ImmutableMap, [simple type, class
com.walmart.services.common.enums.ShipMethod] -> [simple type, class
com.walmart.services.shipprice.api.DetailedShipPrice]]
Thanks
When dealing with Guava types, you will want to use Guava datatype module (https://github.com/FasterXML/jackson-datatype-guava). It is not a problem of just having abstract type; but Guava also uses builder-style instead of constructors.