Reputation: 2728
I have this JSON file into my assets. I am parsing it using Gson into the following model class:
public class SearchRequest {
private ArrayList<String> _source;
private int from;
private int size;
private Object sort;
private Object query;
public void setFrom(int from) {
this.from = from;
}
public void setSize(int size) {
this.size = size;
}
public void setArtist(String artistName) {
Gson gson = new Gson();
JsonObject object = gson.toJsonTree(query).getAsJsonObject();
JsonArray should = object.getAsJsonObject("function_score").getAsJsonObject("query")
.getAsJsonObject("bool").getAsJsonArray("should");
should.get(0).getAsJsonObject().getAsJsonObject("match").addProperty("album_artist", artistName);
should.get(1).getAsJsonObject().getAsJsonObject("nested").getAsJsonObject("query")
.getAsJsonObject("bool").getAsJsonArray("must").get(0).getAsJsonObject()
.getAsJsonObject("match").addProperty("tracks.artist", artistName);
query = gson.fromJson(object.toString(), query.getClass());
}
}
When I convert this JSON into an object of this class, the query
object becomes a LinkedTreeMap
. But in this conversion, the key offset
which is an integer, becomes double. In my JSON (line number 50), offset
is 0
, but after conversion, its 0.0
. Screenshot:
Why is this happening? How to fix this?
Upvotes: 2
Views: 5688
Reputation: 21115
How to fix this?
It's not a subject to be fixed and nothing to be worried about.
Why is this happening?
Your JSON<->Java mapping does not provide any mappings except the top-most one. That makes Gson work like that due to lack of the target type information, and LinkedTreeMap
is used internally. Literals like 0
that may look like integers are also legal floating point values from the JSON format point of view: the JSON specification declares numbers only, and does not make any corrections on "integerness". Having no enough information on deserializing the data types, Gson applies the default parsing policies, and chooses java.lang.Double
as a type that can hold any other standard numeric values that can hold less significance bits (long
s can fit the room of double
s easily; but not sure what Gson does for BigDecimal
s -- JSON specifications does not seem to make any limits). So this is just internal Gson representation and you have a few options on that:
LinkedTreeMap
s. Tedious? Maybe. But much more power in type safety, javac
control, or your favorite IDE navigation and suggestions.getAsJsonObject()
, getAsJsonArray()
, getAsInt()
, and more allowing to get the target object in the representation you want. For example,final Object value = searchRequest.query
.get("function_score").getAsJsonObject()
.get("functions").getAsJsonArray()
.get(0).getAsJsonObject()
.get("linear").getAsJsonObject()
.get("date").getAsJsonObject()
.get("offset").getAsInt();
System.out.println(value + " " + value.getClass());
gives:
0 class java.lang.Integer
because of get("offset").getAsInt()
that's internally implemented as return isNumber() ? getAsNumber().intValue() : ...;
for JSON primitives.
date
JSON tree and convert it to a special mapping having the private int offset;
field declared: gson.fromJson(dateJsonObject, DateMapping.class)
.Again, Gson just does not have enough type information and works really fine.
Upvotes: 1