Object Autoconvert to Double with Serialization/GSON

倾然丶 夕夏残阳落幕 提交于 2019-12-25 04:24:19

问题


I ran into a problem when developing an application that uses Gson to serialize objects and deserialize them. However, I ran into a problem that I cannot explain the cause of and after a while, I narrowed down the problem to this SSCCE:

import com.google.gson.Gson;

/**
 * demonstrates the issue at hand
 */
public class Probs {
    public Probs () {
        //holds the byte array form of the JSON data
        byte[] info = new byte[1];

        //get the JSON for a data object and store it in the byte array
        Gson gson = new Gson();
        Data before = new Data(1);
        info = gson.toJson(before).getBytes();

        //reassemble the JSON data as a string
        String json = new String(info);
        System.out.println("JSON string: " + json);

        //reconstruct the Data object from the JSON data
        Data after = gson.fromJson(json, Data.class);

        //attempt to get the "num" value and convert it to an integer
        Object val = after.getNum();
        System.out.println("Class name: " + val.getClass().getName()); //is java.lang.Double (why isn't it java.lang.Object?)
        Integer num = (Integer)val; //produces "java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer"
        System.out.println("Number: " + num);
    }

    public static void main(String[] args) {
        new Probs();
    }
}

/**
 * holds the one piece of data
 */
class Data {
    Object num;
    public Data(int num) {
        this.num = num;
        System.out.println("Object value: " + this.num);
    }

    public Object getNum () {
        return this.num;
    }
}

I did read this post but it did not appear to have any accepted answers. Because of the way I use it in my application, I need to have the Data object store its data as an Object and be able to cast it later to a different type. When I deserialize the data object and call its getNum(), I thought that should return an Object (since that is its return type). In my application, I need to be able to convert that type into an Integer. However, the JVM appears to convert the Object (val) into a Double because the getClass() reveals that it is a Double and not an Object. Then when I try to convert it to an integer via a cast it fails because it is apparently a Double and not an Object.

My question is: why is val a Double and not an Object (what am I not understanding)?

Thank you for your help


回答1:


The issue is the JSON spec, and what you're doing.

The JSON spec only specifies a single numeric type, which can a include a decimal point and a fractional portion:

2.4. Numbers

The representation of numbers is similar to that used in most
programming languages. A number contains an integer component that
may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part.

JSON parsers are left to decide for themselves what to do with that numeric type when parsing/mapping the JSON.

In your case, your Data class has num defined as Object. This gives Gson no hint as to what specific Java numeric type you'd like the JSON numeric type mapped to. The authors of Gson decided to use a Double when this is the case regardless of whether the number in the JSON includes a decimal + fraction or not.

This actually makes perfect sense when you consider that an integer can be expressed as a double, but not the other way around. Using a single type rather than parsing the number and deciding if it's a int or a double provides consistent behavior.

It's unclear why you aren't using Integer (or int) for num in your Data object if that's what you expect/need. You state you need to cast to Integer "later" which means the only thing that object can be in the first place is an Integer; any other casting attempt would fail.



来源:https://stackoverflow.com/questions/21920436/object-autoconvert-to-double-with-serialization-gson

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!