问题
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