0

I am trying websockets on android using this library WebSocketRails-Android but I want to replace Jackson with Google's Gson but I am having a problem on deserialization. So on receiving a JSON string like this

[["websocket_rails.subscribe",{"id":1676395261,"channel":null,"user_id":null,"data":{"message":"Connected successfully to 82c6"},"success":true,"result":null,"token":null,"server_token":null}]]

Gson deserializes it and gives me the id = 1.676395261E9

I am deserializing like this

@Override
public void onStringAvailable(String data) {

    Gson gson = new Gson();
    Type type = new TypeToken<List>() {}.getType();

    List<Object> list;

    list = gson.fromJson(data, type);
    ...
}

Any help would be appreciated

UPDATE: Endend up creating a function converting that double id to an int. Thanks for your answers though.

Alex
  • 23
  • 8
  • Possible [duplicate](http://stackoverflow.com/questions/4318458/how-to-deserialize-a-list-using-gson-or-another-json-library-in-java). – Mohamad Elghawi Feb 10 '16 at 17:19

5 Answers5

0

I've never seen this happening before, so it may be an error on the way your server is returning stuff or in the Gson library itself(I don't think so). As your number is smaller than the range supported by int type, it's probably going to be really time consuming to find out what's going on. So I would recommend you to return your ID as a String and then use Integer.parseInt(); This may solve your problem

Jefferson Tavares
  • 983
  • 1
  • 8
  • 23
0

Create java classes like the following

public class Response {
        @SerializedName("id")
        int id;
        @SerializedName("data")
        Data data;
        @SerializedName("channel")
        String channel;
        @SerializedName("user_id")
        int userId;
        @SerializedName("success")
        boolean isSuccess;
        @SerializedName("result")
        String result;
        @SerializedName("token")
        String token;
        @SerializedName("server_token")
        String serverToken;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getChannel() {
            return channel;
        }

        public void setChannel(String channel) {
            this.channel = channel;
        }

        public int getUserId() {
            return userId;
        }

        public void setUserId(int userId) {
            this.userId = userId;
        }

        public boolean isSuccess() {
            return isSuccess;
        }

        public void setIsSuccess(boolean isSuccess) {
            this.isSuccess = isSuccess;
        }

        public String getResult() {
            return result;
        }

        public void setResult(String result) {
            this.result = result;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public String getServerToken() {
            return serverToken;
        }

        public void getData(){
            return data;
        }

        public void setServerToken(String serverToken) {
            this.serverToken = serverToken;
        }


        public static class Data {
            @SerializedName("message")
            String message;

            public String getMessage() {
                return message;
            }

            public void setMessage(String message) {
                this.message = message;
            }
        }

    }

and use Gson in the following way to deserialize the object

Type type = new TypeToken<List<Response>() {}.getType();
List<Response> list = new Gson().fromJson(data, type);

// you can now get the correct int value as follows
list.get(0).getId(); // will be 1676395261
Much Overflow
  • 3,142
  • 1
  • 23
  • 40
0

Gson deserializes it and gives me the id = 1.676395261E9

This is not likely to happen if you use Gson correctly. If I would implement this, I would create a class to retrieve the deserialized data into that class. So I would create a class like this.

public class Response {

    private long id;
    private String channel;
    private String user_id;
    // .... Other variables
    private Data data;


    // Declare an empty constructor
    public Response() {

    }

    public class Data {
        private String message;

        public String getMessage() {
            return message;
        }
    }

    // Declare all getters
    public long getId() {
        return id;
    }

    // .... 
}

Now create another class which is a list of Response.

public class ResponseList {

    private ArrayList<Response> list;    // Use the exact name from your json.

    // Declare an empty constructor
    public ResponseList() {

    }

    // Declare all getters
    public ArrayList<Response> getList() {
        return list;
    }
}

Now, use Gson to parse the json data

ResponseList responseList = new Gson().fromJson(data, ResponseList.class);

Here's the user guide from github.

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
0

Created a function parsing the double as a string and then with the appropriate substringing etc converted back to an int.

Alex
  • 23
  • 8
0

I had the same problem. And create manually.

DefaultValues

public final class Values {
    static final Map<Class<?>, Object> defaultValues = new HashMap();

    // load
    static {
        defaultValues.put(boolean.class, Boolean.FALSE);
        defaultValues.put(byte.class, (byte) 0);
        defaultValues.put(short.class, (short) 0);
        defaultValues.put(int.class, 0);
        defaultValues.put(long.class, 0L);
        defaultValues.put(char.class, '\0');
        defaultValues.put(float.class, 0.0F);
        defaultValues.put(double.class, 0.0);
        defaultValues.put(Boolean.class, Boolean.FALSE);
        defaultValues.put(Byte.class, (byte) 0);
        defaultValues.put(Short.class, (short) 0);
        defaultValues.put(Integer.class, 0);
        defaultValues.put(Long.class, 0L);
        defaultValues.put(Character.class, '\0');
        defaultValues.put(Float.class, 0.0F);
        defaultValues.put(Double.class, 0.0);
    }

    public static final <T> T defaultValueFor(Class<T> clazz) {
        if (!defaultValues.containsKey(clazz)) return null;
        return (T) defaultValues.get(clazz);
    }

}

ObjectAdapter

public class ObjectAdapter implements JsonDeserializer<java.lang.Object>, InstanceCreator<java.lang.Object>, JsonSerializer<java.lang.Object> {
    @Override
    public Object createInstance(Type type) {
        Object result = null;
        Constructor c = null;
        final Class clazz;

        if (type instanceof ParameterizedType) {
            clazz = TypeToken.getParameterized(((ParameterizedType) type).getRawType(), ((ParameterizedType) type).getActualTypeArguments()).getRawType();
        } else {
            clazz = (Class) type;
        }
        for (Constructor construtor : clazz.getConstructors()) {
            if (c == null || c.getParameterTypes().length > construtor.getParameterTypes().length)
                c = construtor;
        }
        try {
            if (c != null && c.getParameterTypes().length > 0) {
                Object[] param = new Object[c.getParameterTypes().length];
                boolean b = c.isAccessible();
                c.setAccessible(true);
                for (int index = 0; index < c.getParameterTypes().length; index++) {
                    if (c.getParameterTypes()[index].isPrimitive()) {
                        if (long.class.isAssignableFrom(c.getParameterTypes()[index]) || int.class.isAssignableFrom(c.getParameterTypes()[index]) ||
                                short.class.isAssignableFrom(c.getParameterTypes()[index]) || byte.class.isAssignableFrom(c.getParameterTypes()[index]) ||
                                float.class.isAssignableFrom(c.getParameterTypes()[index]) || double.class.isAssignableFrom(c.getParameterTypes()[index]))
                            param[index] = 0;
                        else if (char.class.isAssignableFrom(c.getParameterTypes()[index]))
                            param[index] = '\u0000';
                        else if (boolean.class.isAssignableFrom(c.getParameterTypes()[index]))
                            param[index] = false;
                        else
                            throw new RuntimeException(c.getTypeParameters()[index].getName());
                    } else if (!Object.class.equals(c.getParameterTypes()[index])) {
                        param[index] = Values.defaultValueFor(c.getParameterTypes()[index]);
                    } else
                        param[index] = null;
                }
                result = c.newInstance(param);
                c.setAccessible(b);
            } else if (c != null) {
                result = c.newInstance();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return result;
    }

    @Override
    public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Object result = null;
        if (json.isJsonObject()) {
            final JsonObject jsonO = json.getAsJsonObject();
            try {
                Class c = (Class) typeOfT;
                if (c.isEnum()) {
                    for (Enum<?> e : ((Enum<?>)typeOfT).getClass().getEnumConstants()) {
                        if (e.name().equals(jsonO.getAsString())) {
                            result = e;
                        }
                    }
                } else {
                    result = this.createInstance(typeOfT);
                    do {
                        for (final Field field : c.getDeclaredFields()) {
                            if (!Modifier.isTransient(field.getModifiers()) && !Modifier.isFinal(field.getModifiers())) {
                                String name = field.getType().getName() + "." + field.getName();
                                if (!jsonO.has(name))
                                    name = field.getName();
                                Class type;
                                if (field.getGenericType() instanceof ParameterizedType) {
                                    type = TypeToken.getParameterized(((ParameterizedType) field.getGenericType()).getRawType(), ((ParameterizedType) field.getGenericType()).getActualTypeArguments()).getRawType();
                                } else {
                                    type = TypeToken.get(field.getType()).getRawType();
                                }
                                final boolean b = field.isAccessible();
                                field.setAccessible(true);
                                JsonElement element = jsonO.get(name);
                                if (element != null) {
                                    if (String.class.isAssignableFrom(type))
                                        field.set(result, element.getAsString());
                                    else if (element.isJsonArray())
                                        field.set(result, context.deserialize(element.getAsJsonArray(), type));
                                    else if (java.lang.Object.class.isAssignableFrom(type) && !element.isJsonPrimitive())
                                        field.set(result, context.deserialize(element.getAsJsonObject(), type));
                                    else if (Serializable.class.isAssignableFrom(type) && element.isJsonPrimitive())
                                        field.set(result, context.deserialize(element, type));
                                    else
                                        field.set(result, context.deserialize(element, type));
                                }
                                field.setAccessible(b);
                            }
                        }
                    } while ((c = c.getSuperclass()) != null);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        } else if (json.isJsonPrimitive()) {
            final JsonPrimitive jsonP = json.getAsJsonPrimitive();
            if (Long.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsLong();
            else if (Integer.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsInt();
            else if (Short.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsShort();
            else if (Byte.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsByte();
            else if (Double.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsDouble();
            else if (Float.class.isAssignableFrom((Class) typeOfT)) {
                result = jsonP.getAsFloat();
            } else if (Character.class.isAssignableFrom((Class) typeOfT)) {
                result = jsonP.getAsCharacter();
            } else if (Boolean.class.isAssignableFrom((Class) typeOfT))
                result = jsonP.getAsBoolean();
            else if (String.class.isAssignableFrom(((Class) typeOfT)))
                result = jsonP.getAsString();
            else if (Enum.class.isAssignableFrom((Class) typeOfT))
                result = Enum.valueOf((Class<Enum>) typeOfT, jsonP.getAsString());
            else
                throw new JsonParseException("Primitive is not supported");
        } else
            throw new JsonParseException("json is not a json Object");
        return result;
    }

    @Override
    public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
        final JsonElement result;
        if (Long.class.isAssignableFrom((Class) typeOfSrc) || Integer.class.isAssignableFrom((Class) typeOfSrc) || Short.class.isAssignableFrom((Class) typeOfSrc) ||
                Byte.class.isAssignableFrom((Class) typeOfSrc) || Double.class.isAssignableFrom((Class) typeOfSrc) || Float.class.isAssignableFrom((Class) typeOfSrc)) {
            result = new JsonPrimitive((Number) src);
        } else if (Character.class.isAssignableFrom((Class) typeOfSrc)) {
            result = new JsonPrimitive((Character) src);
        } else if (Boolean.class.isAssignableFrom((Class) typeOfSrc))
            result = new JsonPrimitive((Boolean) src);
        else if (String.class.isAssignableFrom((Class) typeOfSrc))
            result = new JsonPrimitive((String) src);
        else if (Arrays.class.isAssignableFrom((Class) typeOfSrc) || ArrayList.class.isAssignableFrom((Class) typeOfSrc)) {
            result = new JsonArray();
            if (Arrays.class.isAssignableFrom((Class) typeOfSrc)) {
                for (Object object : Arrays.asList((Object[]) src)) {
                    if (Long.class.isAssignableFrom(object.getClass()) || Integer.class.isAssignableFrom(object.getClass()) || Short.class.isAssignableFrom(object.getClass()) ||
                            Byte.class.isAssignableFrom(object.getClass()) || Double.class.isAssignableFrom(object.getClass()) || Float.class.isAssignableFrom(object.getClass())) {
                        ((JsonArray) result).add((Number) object);
                    } else if (Character.class.isAssignableFrom(object.getClass())) {
                        ((JsonArray) result).add((Character) object);
                    } else if (Boolean.class.isAssignableFrom(object.getClass()))
                        ((JsonArray) result).add((Boolean) object);
                    else if (String.class.isAssignableFrom(object.getClass()))
                        ((JsonArray) result).add((String) object);
                    else {
                        TypeVariable type = ((Class<ArrayList>) typeOfSrc).getTypeParameters()[0];
                        ((JsonArray) result).add(context.serialize(object, type));
                    }

                }
            } else {
                ArrayList iterable = (ArrayList) src;
                for (Object object : iterable) {
                    Class c = object.getClass();
                    if (Long.class.isAssignableFrom(object.getClass()) || Integer.class.isAssignableFrom(object.getClass()) || Short.class.isAssignableFrom(object.getClass()) ||
                            Byte.class.isAssignableFrom(object.getClass()) || Double.class.isAssignableFrom(object.getClass()) || Float.class.isAssignableFrom(object.getClass())) {
                        ((JsonArray) result).add((Number) object);
                    } else if (Character.class.isAssignableFrom(object.getClass())) {
                        ((JsonArray) result).add((Character) object);
                    } else if (Boolean.class.isAssignableFrom(object.getClass()))
                        ((JsonArray) result).add((Boolean) object);
                    else if (String.class.isAssignableFrom(object.getClass()))
                        ((JsonArray) result).add((String) object);
                    else
                        ((JsonArray) result).add(context.serialize(object, object.getClass()));
                }
            }
        } else {
            Class c = src.getClass();
            if (c.isEnum()) {
                result = new JsonPrimitive(Enum.valueOf(c, src.toString()).toString());
            } else {
                result = new JsonObject();
                do {
                    for (Field field : c.getDeclaredFields()) {
                        if (!Modifier.isTransient(field.getModifiers()) && (!Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers()))) {
                            final boolean b = field.isAccessible();
                            try {
                                field.setAccessible(true);
                                String name = field.getName();
                                if (((JsonObject) result).has(name))
                                    name = field.getType().getName() + "." + field.getName();
                                final Class type;
                                if (field.getGenericType() instanceof ParameterizedType) {
                                    type = TypeToken.getParameterized(((ParameterizedType) field.getGenericType()).getRawType(), ((ParameterizedType) field.getGenericType()).getActualTypeArguments()).getRawType();
                                } else {
                                    type = TypeToken.get(field.getType()).getRawType();
                                }
                                if (type.isPrimitive()) {
                                    if (Number.class.isAssignableFrom(type))
                                        ((JsonObject) result).addProperty(name, (Number) field.get(src));
                                    else if (Character.class.isAssignableFrom(type))
                                        ((JsonObject) result).addProperty(name, (Character) field.get(src));
                                    else if (Boolean.class.isAssignableFrom(type))
                                        ((JsonObject) result).addProperty(name, (Boolean) field.get(src));
                                    else
                                        ((JsonObject) result).addProperty(name, (field.get(src) != null) ? String.valueOf(field.get(src)) : null);
                                } else if (String.class.isAssignableFrom(type))
                                    ((JsonObject) result).addProperty(name, (field.get(src) != null) ? String.valueOf(field.get(src)) : null);
                                else if (Number.class.isAssignableFrom(type))
                                    ((JsonObject) result).addProperty(name, (Number) field.get(src));
                                else if (Character.class.isAssignableFrom(type))
                                    ((JsonObject) result).addProperty(name, (Character) field.get(src));
                                else if (Boolean.class.isAssignableFrom(type))
                                    ((JsonObject) result).addProperty(name, (Boolean) field.get(src));
                                else
                                    ((JsonObject) result).add(name, context.serialize(field.get(src), type));

                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                                throw new RuntimeException(e);
                            } finally {
                                field.setAccessible(b);
                            }
                        }
                    }
                } while ((c = c.getSuperclass()) != null);
            }
        }
        return result;
    }
}

How use :

List<Object> list = new GsonBuilder().registerTypeHierarchyAdapter(java.lang.Object.class, new ObjectAdapter()).create().fromJson(data, type);

Crammeur
  • 678
  • 7
  • 17