Getting "declares multiple JSON fields named" error when serializing with GSON - java

Type type = new TypeToken<HashMap<String , MovieDb>>() {}.getType();
gson.fromJson(json, type); //ERROR HERE !!!
When I convert from Json to the hashmap object it works fine without minifying enabled. But when minify is enabled it gives me the following error at this line:
java.lang.IllegalArgumentException: class a.a.a.a.b declares multiple JSON fields named a
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:172)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:102)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.b.a(CollectionTypeAdapterFactory.java:53)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:117)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:166)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:102)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.g.a(MapTypeAdapterFactory.java:126)
at com.google.b.e.a(Gson.java:458)
at com.google.b.e.a(Gson.java:926)
at com.google.b.e.a(Gson.java:892)
at com.google.b.e.a(Gson.java:841)
at com.techy.nateshmbhat.moviego.i.onPreExecute(MovieInterface.java:180)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:648)
at android.os.AsyncTask.execute(AsyncTask.java:595)
at com.techy.nateshmbhat.moviego.i.b(MovieInterface.java:101)
at com.techy.nateshmbhat.moviego.a.a(Activity_InTheaterMovies.java:55)

Your error is most propably because you minify two fields to a same name a. Something like:
#SerializedName("a")
Long veryLongFieldName;
#SerializedName("a")
Long anotherVeryLongFieldName;
Note that these can be either in the same class or if using inheritance it is enough that they are in the same inheritance tree. Gson can not assign two values to one minimized field name a.
It could of course also be that you have minimized some field to a name that is already reserved by some other unminimized field.

I've faced this issue when I had context property/variable in the model class

Related

Jackson Deserialize To Concrete Class Based On Type

I have what I believe should be a simple use case.
I would like to serialize a POJO with type metadata (preferably a simple name I come up with, not the fully qualified class/package name), and later have Jackson deserialize the JSON back into the concrete class it came from by using this metadata. There is no inheritance hierarchy among classes being serialized and deserialized.
My scenario is I have a service which accepts multiple file types. For each file uploaded, the client can retrieve JSON data whose structure and type depends on the file it came from. Thus when I retrieve JSON from the service, it's not known what the concrete class is to deserialize to. I would like Jackson to figure this out based on metadata which it supplies.
For example, I'd like to be able to do this:
String json = ... // get JSON from the service
Object obj = mapper.readValue(json, Object.class) // concrete class is not known
System.out.println(obj.getClass()) // I want this to be MyConcreteClass.class
There is no inheritance hierarchy among JSON types returned.
I don't want to reveal package names or other internal service
details/structure.
I have control over Jackson's serialization process
Relevant question: Can jackson determine root object type to deserialize to when json includes type property?
Thank you so much for your help!
This can be achieved using Jackson's JavaType:
String className = "class.name.from.json.service";
JavaType dtoType = TypeFactory.defaultInstance().constructFromCanonical(className);
Object dto = new ObjectMapper().readValue(InputStream, dtoType);
assert dto.getClass().equals(dtoType.getRawClass());

Gson fromJson returning empty JsonObject

So, I've got a String that is the result of a toJson method I've implemented on a class, and have confirmed in my test code that it is the correct Json representation of my class. My goal is to turn this String into a JsonObject and pass it to a constructor, using Gson. However, I'm running into an odd problem.
This is the code I'm calling:
Gson gson = new Gson();
JsonObject jObj = gson.fromJson(jsonString, JsonObject.class);
I have used literally this exact same snippet of code before in many places in my project, for other classes, and it has worked fine. I even copied one of those functional snippets of code into this test class and tried it. However, every version I try results in the same thing--jObj is an empty set of brackets.
I don't understand how it's happening. I've confirmed that jsonString has all the fields it should need. Why is Gson returning an empty JsonObject? No exceptions are being thrown.
Ok so i know this is a little old but I had the same exact issue. The resolution was changing the jar file. I had a similar code sample working in another project but then I was experiencing the exact same problem in another. Well the problem was an older gson-2.1.jar. Updated the problem application to the matching gson-2.3.1.jar and all was working. Hope this helps.
From your comment that says the string is {"varName":1, "otherVarName":2, "thirdVarName":3.4}, looks like the serialized object was a Map. You may need to specify the type token:
gson.fromJson(jsonString, new TypeToken<Map<K,V>>() {}.getType());
where K and V are the key and value types of the map. If it is not a Map, specify whatever class the jsonString was obtained from.
For my case, I was accidentally using the following initializer in my dagger module.
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
I removed the setFieldNamingPolicy and it worked.
I had this issue as well.
I was using
return gson.fromJson(response, JsonObject::class.java)
And I was receiving an object with only the default values populated.
I had to explicitly define the serialized names for each property in my JsonObject class that was different from how it was named in the json response.
For example, if in the json I was parsing the field name was "total_score', but my JsonObject had a field named "totalProperty", I had to use the #SerialedName annotation to define the relationship.
#SerializedName("total_score")
val TotalScore : Int = 0

Error while Parsing json into scala case class

In my spring(mvc) web application, I am using org.codehaus.jackson.map.ObjectMapper in my scala code to map my json to scala objects using case classes. My Json String is an array of json objects objects. so I am using:
val user = mapper.readValue(myJson, classOf[List[MyClass]])
This line throws an error:
Exception in thread "main"
org.codehaus.jackson.map.JsonMappingException: Can not construct
instance of scala.collection.immutable.List, problem: abstract types
can only be instantiated with additional type inform
Am I using it right or is there any other way?
The problem is the Java type erasure. classOf[List[MyClass]] at runtime is the same as classOf[List[_]]. That is why Jackson cannot know, which types of the elements to create.
Luckily Jackson does support parsing with the JavaType, which describes the types themselves.
Here a simple sample in Java:
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, MyClass.class);
mapper.readValue(myJson, type);
Because of type erasure, the parameterized type of the List is lost at runtime.
Instead, use the Scala module for Jackson and you can simply do:
mapper.readValue(myJson, new TypeReference[List[MyClass]])
So long as the Scala module has been registered - this means a Scala List will be created.

Instantiate generic based on property file setting

I'm building a data driven test system. I have done this before in XML but json is giving me some interesting issues.
For each request and response type json, I have a setting in my script where I specify a pojo type. This type is instantiated to a class object thats passed to jackson to marshal the json into a usable pojo. so its like this:
"responseType": "java.util.List",
eventually gets pumped to
Class<?> reponseType = null;
try {
if (d.shouldPass) {
reponseType = Class.forName(d.responseType);
}
} catch (ClassNotFoundException e) {
throw new RequestResponseTypeInvalid(testName);
}
and I have usable class info to use in jackson. My problem is I need to do this:
"responseType": "java.util.List<foo>",
otherwise complex json types parse as hashmaps instead of pojo's. I suppose I can get creative and put something in to go from hashmap to pojo if I need to but I was wondering if there was any straight forward way to do this.
I suppose another way is to implement a factory class where I could say list_foo in the property file and have the factory class map that to an actual class object. That wouldn't be very hard but not as easy as just using the property.
thanks
You can't do this in the way that you're hoping, I'm afraid. Generics are a compile-time thing only, and can't be used in this way at runtime, because of type erasure.
The best you could do would be to have some list_foo properties, and map these explicitly to List<Foo> and so in in your code. But you can't do it by reflection.

Unmarshalling a date from an XML String to entity using JAXB

When I use JAXB, there is something wrong.
I convert entity to a xml String and everything is ok.
But when I convert xml String back to entity, some information is lost (All of them have the same type java.util.Date).
In entity:
public Date flightBaseDate;
In xml:
<flightBaseDate>2013-09-16T00:00:00 08:00</flightBaseDate>
after unmarshalling, getFlightBaseDate() returns null.
I googled.
Following one suggestion, I used # in my entity.
Then it is:
#XmlElement(name = "timestamp", required = true)
public Date flightBaseDate;
I'm sure it will be perfect,
but...throws Exception, like this:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "flightBaseDate"
this problem is related to the following location:
at public java.lang.String com.wonders.nlia.omms.vo.FlightServiceInfoVo.getFlightBaseDate()
at com.wonders.nlia.omms.vo.FlightServiceInfoVo
this problem is related to the following location:
at public java.lang.String com.wonders.nlia.omms.vo.FlightServiceInfoVo.flightBaseDate
at com.wonders.nlia.omms.vo.FlightServiceInfoVo
Why JAXB could not distinguish between the property and its getMethod?
How to solve it?
Platform:jdk7 win7 eclipse tomcat wtp
My Unmarshalling code is:
JAXBContext context = JAXBContext.newInstance(FlightServiceInfoVo.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
FlightServiceInfoVo flightServiceInfoVo =(FlightServiceInfoVo)unMarshaller.unmarshal(new StringReader(flightServiceInfoVoXml));
flightServiceInfoVoXml is a String.
You can configure JAXB in many different ways. You have chosen Annotations to define the binding (this is allright, do not worry).
I strongle recommend you read about that technique first as there are a lot of pitfalls. Here is a link to a good tutorial. Here is the part in the tutorial which explains why your binding does not work: XmlAccessorType part
As for your specific issue:
In general you have to tell JAXB what and how to bind the java object to it's XML representation. If you do not do anything, then by default all public members of your class are bound (as you can read here).
Additionally you have chosen to annotate the getter method of your public member, which then just pushes the same variable twice to your XML which later causes the exception you see.
To fix your error, either specify a different mapping strategy for your class by putting e.g. (#XmlAccessorType(XmlAccessType.NONE)) before your class declaration or move the annotation from the getter method to the property.
By the way: Having a getter method and a public member variable does not make sense at all. So making your member variable private will also fix your issue with JAXB and be a lot better for your class design.
the exception clearly says that the property name is duplicated, so check you class for a property 'flightBaseDae', it should be unique. remove the duplicate then unmarshall it

Categories