Flex JSON无法正确序列化/反序列化LinkedHashMap

时间:2013-07-08 04:31:12

标签: java json flexjson

我尝试将LinkedHashMap数据序列化和deseriliaze如下:

LinkedHashMap<String, Object> o = new LinkedHashMap<String, Object>();
o.put("1", "a");
o.put("2", "b");
o.put("3", "c");
o.put("4", new BigDecimal("9999999999999999999999.00999999999999999999999"));

String serialize = new JSONSerializer().deepSerialize(o);
System.out.println("serialize" + serialize);

LinkedHashMap deserialize = new JSONDeserializer<LinkedHashMap>().deserialize(serialize, LinkedHashMap.class);
System.out.println("deserialize:" + deserialize);

我得到ClassCastException:

serialize{"1":"a","2":"b","3":"c","4":9999999999999999999999.00999999999999999999999}
Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
    at com.JSONUtil.main(JSONUtil.java:161)

所以我在反序列化时尝试了稍微不同的方法,如下所示:

HashMap deserialize = new JSONDeserializer<HashMap>().deserialize(serialize, HashMap.class);
System.out.println("deserialize:" + deserialize);

这次我得到了结果,但是地图是无序的(我想因为它现在正在使用HashMap)。此外,BigDecimal值不会像原始格式一样显示。

deserialize:{3=c, 2=b, 1=a, 4=1.0E22}

FlexJSON似乎存在排序地图的问题。我想这是因为它无法像下面的例子那样放置'class'条目,例如。

"class":"ch.qos.logback.classic.Logger","debugEnabled":true,"errorEnabled":true,"infoEnabled":true}

或者还有另一种方法可以做到这一点。有人可以帮忙吗? 谢谢


按照chubbsondubs的建议引入ObjectFactory:

LinkedHashMap deserialize = new JSONDeserializer<LinkedHashMap>()
.use(LinkedHashMap.class, new ObjectFactory() {
public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
    System.out.println("mymap:"value);
}
}).deserialize(serialize, LinkedHashMap.class);

值对象具有HashMap类型,并打印:

mymap:{3=c, 2=b, 1=a, 4=flexjson.JsonNumber@104fc23}

1 个答案:

答案 0 :(得分:2)

默认情况下,没有输入信息的对象被解释为HashMap,在文档中对此进行了解释。不使用HashMap的时间是它是否可以从嵌入的类属性(可以在网络上运行,但在网络上不安全),对象路径指定的类型,或者如果要反序列化为来确定对象的类型一个可以解释类型的类型化对象。

因此,像标准集合这样的类,Flexjson无法从Collection / Map类中推断出包含的类型,因为它们是运行时的简单Object引用。数字是JSON未指定任何类型信息的另一个区域。当我们将数字映射到Java时,它可能是以下几种类型之一:byte,short,int,long,BigInteger,float,double,BigDecimal。如果没有指定输入信息,Flexjson必须拨打电话。默认情况下,如果是小数则使用double,如果是整数则使用long。在你的情况下它是一个双倍,这就是为什么它以指数格式显示它。

您必须指定所需的类型。通过使用类型化对象,在对象路径上配置类型或通过创建自定义ObjectFactory。我认为除非您可以创建类型化对象,否则ObjectFactory是您的唯一选择。原因是因为地图中的值因类型而异。有些条目是字符串,另一个是BigDecimal。所以你必须有一个特殊的ObjectFactory知道实例化一个LinkedHashMap并复制从源到目标的所有键,如果源的值是JsonNumber则将它们转换为BigDecimal。