karol-brejna-i / tigergraph-restpp-client

TigerGraph's REST++ API client in Java.
1 stars 1 forks source link

GSON deserializes int as Double... #5

Open karol-brejna-i opened 2 years ago

karol-brejna-i commented 2 years ago

It turns out it is a default behaviour of GSON.

For example, int the following response:

class QueryResponse {
version: class Version {
edition: enterprise
api: v2
schema: 0
}
error: false
message:
results: [{result=[{personId=2.199023255711E12, personFirstName=David, personLastName=Alonso, xCount=1.0, yCount=1.0, xyCount=2.0}]}]
requestId: null
}

personId, xCount are long numbers. They were deserialized to Double.

In one of the newer versions of GSON there is a switch that disables the "feature".

See: https://github.com/google/gson/pull/1290

Use the switch to make integers great again...

karol-brejna-i commented 2 years ago

Try to add:

    public JSON() {
        gson = createGson()
            .registerTypeAdapter(Date.class, dateTypeAdapter)
            .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
            .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
            .registerTypeAdapter(LocalDate.class, localDateTypeAdapter)
            .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)   <------------------------- this one
            .create();
    }

in src/main/java/io/github/karol_brejna_i/tigergraph/restppclient/invoker/JSON.java

bdoobli commented 2 years ago
    json = "{\"kind\": \"books#volumes\", \"totalItems\": 0, \"items\": []}";
    Gson gson = new GsonBuilder()
            .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
            .create();
    gson.fromJson(json, com.google.api.services.books.v1.model.Volumes.class);

==> java.lang.IllegalArgumentException: field com.google.api.services.books.v1.model.Volumes.totalItems has type java.lang.Integer, got java.lang.Long

    json = "{\"kind\": \"books#volumes\", \"totalItems\": 0, \"items\": []}";
    (new Gson()).fromJson(json, com.google.api.services.books.v1.model.Volumes.class);

==> java.lang.IllegalArgumentException: field com.google.api.services.books.v1.model.Volumes.totalItems has type java.lang.Integer, got java.lang.Double

What is a solution to deserialize json com.google.api.services.books.v1.model.Volumes.class ?

karol-brejna-i commented 2 years ago

@bdoobli For me, the following resolved previous issue:

    public static GsonBuilder createGson() {
        GsonFireBuilder fireBuilder = new GsonFireBuilder() ;
        return fireBuilder.createGsonBuilder();
    }

    public JSON() {
        gson = createGson()
            .registerTypeAdapter(Date.class, dateTypeAdapter)
            .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
            .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
            .registerTypeAdapter(LocalDate.class, localDateTypeAdapter)
            .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
            .create();
    }

I see GsonFireBuilder is used here (as opposed to your GsonBuilder. Take a look at the source code (https://github.com/karol-brejna-i/tigergraph-restpp-client/blob/develop/src/main/java/io/github/karol_brejna_i/tigergraph/restppclient/invoker/JSON.java), maybe there are more differences. Please, note, that my code is generated by openapi-generator-cli, I didn't need to handcraft the code (beside setObjectToNumberStrategy)...

bdoobli commented 2 years ago

I tested your GsonFireBuilder without success.

With another deserializer com.google.api.client.json.JsonSolution there is a solution

    String json = "{\"kind\": \"books#volumes\", \"totalItems\": 0, \"items\": []}";
    JsonFactory factory = getDefaultInstance();
    Volumes vs = factory.fromString(json, com.google.api.services.books.v1.model.Volumes.class);

Still wondering how to use Gson with google api services like com.google.api.services.books.v1.model.Volumes