Unable to deserialize alternate name with GSON, AutoValue, and Retrofit 2 - java

I am using retrofit version 2.1.0 to deserialize JSON into pojos. A field in the pojo can be received under different names in the json. To deserialize the field correctly, I used the #serializedName annotation in the following way:
#AutoValue
public abstract class Media implements Parcelable {
#SerializedName(value = "title", alternate = {"name"})
public abstract String title();
// More fields and code
However, for some reason, when the resulting JSON has the field under the key "title", Gson reads it correctly, but when the field is associated with the "name" key, it does not get read.
How can I get GSON to recognize the alternate name during deserialization?

I'm assuming you're using the com.ryanharter.auto.value:auto-value-gson plugin. Support for alternate serialized names was not added until version 0.4.0. Update to com.ryanharter.auto.value:auto-value-gson:0.4.2 and you should then be able to deserialize alternate names.

Seem the problem is related to Parcel.
You might want take a look at this
parceler
#AutoValue
#Parcel
public abstract class Media {
#ParcelProperty("title") public abstract String title();
}

Related

format a json of a class in spring

I am new with spring and I want the json response of my class
public class Mapping { public String name; public Object value; }
be changed from
{"name" : 'value of field name', "value": 'value of field value'}
to
{'value of field name' : 'value of field value'}
I tried #JsonValue and #JsonKey but they didn`t work. how can I do this.
edit:
I want to set the value of key dynamically and based on value of the field name.
edit_P2:
this class, is a model for a single field in json, means an object of it must hold one key and value of my json, like a map, it has key and values, and what i want is to store key in field 'name' and the value in outher field, so when i return this object, it returns the string in field 'name' as key and the other one as value, lets assume name="the key" and value="the value", i want it to be return as "the key":"the value".
Edited in reaction to your comment:
Have your class changed from
public class Mapping {
public String name;
public Object value;
}
to simply this:
public class Mapping {
public String name;
}
and in your code to this:
Mapping myMapping = new Mapping();
myMapping.name = "myValue";
This will be parsed to JSON: {"name":"myValue"}
Additional edit
OK, I think I understood what you want and I think it might be impossible in a single json serialization. Your options would be to create a custom serializer See this article: Jackson – Custom Serializer. Or (in my opinion simpler way) add a method to your class toMap() that will produce your desired map and than convert that map to Json. That will give you desired Json. BTW for simple Json serializer/deserializer that is a wrapper over Json-Jackson library look here: JsonUtils. The library could be found as Maven artifact and on Github (including source code and Javadoc).
Original answer:
You need to use annotation #JsonProperty and its attribute "name". Here is a good article about it: Jackson – Change Name of Field

Problems with sonar changing the names of an object in REST calls by Jackson JSON

I have an object that in its fields is mandatory that some names have '_' for example local_PC instead of localPC.
The problem I have is that I need it to be local_PC and when a call is made to my app they send that field and I can't change it, but sonar launches me error because it must be localPC
Is there any way I can control it by Jackson?
realizing #jsonproperty only allows me to change the names in the output but not in the input of the controller
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
#AllArgsConstructor
public class Example{
private String local_PC;
}
Use #JsonAlias
#JsonAlias is introduced in Jackson 2.9 release. #JsonAlias defines one or more alternative names for a property to be accepted during deserialization i.e. setting JSON data to Java object. But at the time of serialization i.e. while getting JSON from Java object, only actual logical property name is used and not alias. #JsonAlias
#JsonAlias({"local_PC", "localPC"})
private String local_PC;

How does gson maps JSON keys with the fields in Java classes while deserializing the JSON

I am searching for this for quite some time now but still, it is not clear to me. I have a JSON file which looks like this:
{
"Name" : "Foo Bar",
"Grade" : "Some Grade",
"Org" : "Some Org"
}
For deserializing this JSON (using gson) I have created a Java class called StudentDetails.java which looks like this:
public class StudentDetails
{
public String name;
public String grade;
public String org;
}
Now I have a couple of questions regarding this:
Will gson automatically maps the fields in StudentDetails.java with corresponding keys even if the fields start with lower case and keys start from upper case in the JSON file. I have looked for #SerializedName but my code works without even using it. On the contrary if I am using something like #SerializedName("Name) with name field, it's getting assigned to null after deserialization. I am so confused right now.
Will deserialization work without even getter and setter methods? In jackson you write setter and getter methods.
If above is true, does it work even in the case of private fields?
I'm note sure about this one but i think the case only matters after the first character because you normally don't start the name of field with an upper-case character.
Yes GSON will automatically map the fields.
Yes GSON does not need getter/setter
(https://stackoverflow.com/a/6203975/4622620)
Yes GSON can handle private fields because it uses reflections (https://stackoverflow.com/a/28927525/4622620)

How to JSON parse immutable object in Java + Jersey

So I am just trying out Jersey for REST services and it seems to we working out fine. I only expose get services and all of the object types that I expose with these services have an immutable object representation in Java. By default Jersey seems to use a parser (JAXB?), requiring a #XmlRootElement annotation for the class that should be parsed, zero-arg constructor and setters.
I have been using Gson with no zero-arg constructor, no setters and final on all fields with no problems at all. Is there any way to accomplish this with Jersey(i.e. the paser it is using)? I have seen solutions with adapter classes that map data from a immutable object to a mutable representation, but this seems like a lot of boilerplate(new classes, more annotations, etc.) if it can be achieved with Gson without anything added.
Note: 1) I have heard people promote using zero-arg constructor and claim that Gson should not work without it. This is not what I am interested in. 2) I really have tried googling this but my keywords might be off. In other words, humiliate me in moderation.
EDIT 1:
My webservice works if I do like this:
#XmlRootElement
public class Code{
private String code; //Silly object just used for example.
public Code(){}
//(G || S)etters
}
With this class exposing the object:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Set<Code> get(#QueryParam("name") String name) { // Here I want to use a class of my own instead of String name, haven't figured out how yet.
return this.codeService.get(name);
}
If I replace the Code with the following, the webservice stops working:
public class Code{
private final String code;
#JsonCreator
public Code(#JsonProperty("code") String code) {
this.code = code;
}
//Getters omitted
}
What I want is to be able to 1) have immutable objects that can be parsed to/from json and 2) Be able to define something like #RequestBody in Spring MVC for my incoming objects.
Actually this could be pretty easy with Genson. You just need the jar and then configure the Genson feature to use constructors with arguments (if you don't want to put annotations on it).
Genson genson = new GensonBuilder().useConstructorWithArguments(true).create();
// and then register it with jersey
new ResourceConfig().register(new GensonJaxRSFeature().use(genson));
Or you can use JsonProperty on the arguments. See the User Guide for more details.

Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied

I am using Google's GSON package http://code.google.com/p/google-gson/
I am converting JSON to Java.
I have this fragment of code where I do the conversion.
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<QueryProperty>>() {}.getType();
Collection<QueryProperty> queryProperties = gson.fromJson(query, collectionType);
My QueryProperty class has these fields (with getters/setters):
int id;
String uri;
String name;
Set<QueryValue> values;
String selected;
The QueryValue class had these fields (with getters/setters) perviously:
int id;
String uri;
String name;
I now want to be able to have different types of QueryValue.
I want to add a NumericQueryValue class (subclass of QueryValue), so I can pass in a set of bounds with which to query the db.
double lower;
double upper;
And want to make a new ResourceQueryValue (subclass of QueryValue) which looks the same as QueryValue used to:
int id;
String uri;
String name;
Is there anyway I can make this work. That is have a generic QueryValue class, but have the correct subclass returned depending on the parameters that the JSON supplies.
If I have not been clear please do let me know.
Gson does not currently have a simple mechanism for polymorphic deserialization, other than implementing custom deserialization processing. The next release looks like it will provide a built-in solution.
Previous StackOverflow.com Questions And Answers (Some With Examples) On This Topic:
Deserialising a generic with unknown compile time type where a field indicates the type
Parse JSON with no specific structure for a field with GSON
json object serialization/deserialization using google gson
Polymorphism with gson
Sounds like you want to create a custom deserializer if you need to check the values, or an instance creator if you only need to create an instance based on type.

Categories