使用序列化/ GSON将对象自动转换为Double

时间:2014-02-20 21:52:51

标签: java serialization gson

在开发使用Gson序列化对象并反序列化它们的应用程序时遇到了问题。但是,我遇到了一个问题,我无法解释原因,一段时间后,我将问题缩小到这个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;
    }
}

我确实阅读了this post,但似乎没有任何可接受的答案。由于我在应用程序中使用它的方式,我需要让Data对象将其数据存储为Object,并能够将其稍后转换为其他类型。当我反序列化数据对象并调用它的getNum()时,我认为应该返回一个Object(因为这是它的返回类型)。在我的应用程序中,我需要能够将该类型转换为Integer。但是,JVM似乎将Object(val)转换为Double,因为getClass()显示它是Double而不是Object。然后,当我尝试通过强制转换将其转换为整数时,它会失败,因为它显然是Double而不是Object。

我的问题是:为什么val是Double而不是Object(我不理解的是什么)?

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

问题是JSON规范,以及您正在做什么。

JSON spec仅指定数字类型,可以包含小数点和小数部分:

  

2.4。编号

     

数字表示与大多数数字相似   编程语言。数字包含一个整数分量   可以使用可选的减号作为前缀,后面可以是   分数部分和/或指数部分。

在解析/映射JSON时,JSON解析器可以自行决定如何处理该数值类型。

在您的情况下,您的Data班级num定义为Object。这使得Gson没有提示您希望JSON数字类型映射到哪个特定的Java数字类型。无论JSON中的数字是否包含小数+分数,Gson的作者决定使用Double

当你考虑一个整数可以表示为double时,这实际上是完全合理的,但不是相反。使用单一类型而不是解析数字并确定它是int还是double提供了一致的行为。

目前还不清楚为什么你没有在Integer对象int中使用num(或Data},如果这是你期望/需要的话。你声明你需要转换为Integer“稍后”,这意味着对象首先可以是Integer;任何其他的铸造尝试都会失败。