2011-10-31 75 views
0

我正在使用Jackson将JAXB带注释的对象序列化为一个地图对象。下面是一些代码来说明我的问题:如何使用Jackson将对象转换为使用默认打字的地图?

public class Test { 

    @XmlAccessorType(XmlAccessType.NONE) 
    public static class Inner { 
     @XmlAttribute 
     public int foo; 
    } 

    @XmlAccessorType(XmlAccessType.NONE) 
    public static class Outer { 
     @XmlAttribute 
     public String bar; 

     @XmlElement 
     public Inner in; 
    } 

    public static void main(String[] args) throws Exception { 
     ObjectMapper mapper = getMapper(); 

     mapper.enableDefaultTyping(); 

     Inner in = new Inner(); 
     in.foo = 42; 
     Outer out = new Outer(); 
     out.in = in; 
     out.bar = "thecakeisalie"; 

     Object o = mapper.convertValue(out, TreeMap.class); 
     System.out.println(o); 
    } 

    public static ObjectMapper getMapper() { 
     ObjectMapper mapper = new ObjectMapper(); 
     AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); 
     mapper.setAnnotationIntrospector(introspector); 
     return mapper; 
    } 
} 

这将导致以下错误:如果线路mapper.enableDefaultTyping();被省略,代码工作和

Exception in thread "main" java.lang.IllegalArgumentException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object 
at [Source: N/A; line: -1, column: -1] 
    at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2493) 
    at org.codehaus.jackson.map.ObjectMapper.convertValue(ObjectMapper.java:2459) 
    at com.example.test.Test.main(Test.java:49) 
Caused by: org.codehaus.jackson.map.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object 
at [Source: N/A; line: -1, column: -1] 
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163) 
    at org.codehaus.jackson.map.deser.StdDeserializationContext.wrongTokenException(StdDeserializationContext.java:261) 
    at org.codehaus.jackson.map.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:100) 
    at org.codehaus.jackson.map.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:86) 
    at org.codehaus.jackson.map.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:69) 
    at org.codehaus.jackson.map.deser.std.UntypedObjectDeserializer.deserializeWithType(UntypedObjectDeserializer.java:106) 
    at org.codehaus.jackson.map.deser.std.MapDeserializer._readAndBind(MapDeserializer.java:321) 
    at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:249) 
    at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:33) 
    at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2695) 
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1308) 
    at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2489) 
    ... 2 more 

输出以下:

{bar=thecakeisalie, in={foo=42}}

如果我使用映射器序列化为json,它将使用默认的键入。

默认打字与对象转换不兼容,还是我用错了?

回答

2

好的。 Hmmh。这个问题源于某种不兼容的用法:发生的情况是,在序列化时,默认类型只会按照其配置添加类型信息,在这种情况下,类型信息不包括在内(类型不是抽象的,也不是声明为java.lang。目的)。 但是,当反序列化(作为转换的一部分)时,结果类型需要类型信息,因为名义类型是TreeMap<Object,Object>;这就是例外来自的地方。

但是,由于您正在转换为一个地图 - 本质上是一个“无类型”类型 - 您最好关闭只是不启用默认输入。无论如何,该类型的信息将被丢弃。或者,如果您确实想要查看包含的类型信息,则需要执行两阶段处理:启用默认类型启用(使用启用它的映射器)的序列化,以及反序列化为具有缺省值的ObjectMapper的TreeMap打字禁用。

相关问题