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

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

问题描述:

我试图按如下顺序序列化和反序列化LinkedHashMap数据:

I tried to serialize and deseriliaze LinkedHashMap data as follow:

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:

and I get 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)

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

So I tried slightly different approach when deserializing as follow:

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

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

This time I get result but the Map is unordered (I think because it is now using HashMap). In addition, the BigDecimal value is not displayed like the original format.

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

似乎FlexJSON在排序的Map上有问题.我想这是因为它无法像下面的示例一样放置"class"条目,例如.

It appears that FlexJSON has issue with sorted Map. I guess this is because it has no way to put 'class' entry like the example below, eg.

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

或者也许还有另一种方法可以做到这一点.谁能帮忙吗? 谢谢

or perhaps there is another way to do this. Can anyone please help? Thank you

在按照chubbsondubs的建议引入ObjectFactory之后:

After introducing ObjectFactory as suggested by chubbsondubs:

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类型,并显示:

The value object has HashMap type and it prints:

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

默认情况下,不键入信息的对象将解释为HashMap,在文档中对此进行了说明.它不使用HashMap的时间是它是否可以从嵌入式类属性(可以工作,但是在网络上不安全),按对象路径指定的类型,或者是否要反序列化为对象来确定对象的类型.可以解释其类型的类型化对象.

By default an object without typing information is interpreted as HashMap which is explained in the docs. The times it won't use a HashMap is if it can determine the type of the object from either an embedded class property (which works, but is unsafe over the network), a specified type by object path, or if you are deserializing into a typed object that it can interpret the type from.

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

So classes like standard collections there is no way Flexjson can infer the contained type from a Collection/Map class because those are simple Object references at runtime. Numbers are another area where JSON doesn't specify any type information. When we map a number to Java that could be one of several varieties: byte, short, int, long, BigInteger, float, double, BigDecimal. Flexjson has to make a call if no typing information is specified. By default it uses double if its a decimal and long if its an integer. In your case it's a double and that's why it shows it in exponential format.

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

You'll have to specify the types you want. By either using a typed object, configuring a type on an object path or by creating a custom ObjectFactory. I think a ObjectFactory is the only option for you unless you can create typed object. Reason being is because the values in your Map vary in type. Some entries are string where another is BigDecimal. So you'll have to have a special ObjectFactory that knows to instantiate a LinkedHashMap and copy over all the keys from the source to the target converting them to BigDecimal if the value of the source is JsonNumber.