java - 如何使用 Jackson 将对象转换为使用默认类型的 map ?

标签 java json jackson

我正在使用 Jackson 将 JAXB 带注释的对象序列化为 map 对象。这是一些代码来说明我的问题:

    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;
    }
}

这会导致以下错误:

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

如果省略了 mapper.enableDefaultTyping(); 行,则代码将正常工作并输出以下内容:

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

如果我使用映射器序列化为 json,它将使用默认类型。

默认类型与对象转换不兼容,还是我使用错误?

最佳答案

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

但是,由于您要转换为 Map(本质上是“无类型”类型),因此您最好不要启用默认类型。无论如何,该类型信息都会被丢弃。

或者,如果您确实想查看包含的类型信息,则需要进行两阶段处理:在启用默认类型的情况下进行序列化(使用启用了该功能的映射器),并使用具有默认类型的 ObjectMapper 反序列化为 TreeMap已禁用。

关于java - 如何使用 Jackson 将对象转换为使用默认类型的 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7956983/

相关文章:

java - "java.lang.ClassFormatError: Invalid pc in LineNumberTable"的可能原因

java - java中涉及多个对象的比较器实现

java - Hibernate 父表的分组依据

java - 使用 RestFB 时出现 Unicode 错误

java - Spring : detached entity passed to persist

c# - 如何验证 JObject 是否属于特定类型

java - Jackson注释: some are seen,有些没有

java - jackson :反序列化到一个集合

java - jackson 与 JSON : receiving "null" object

java - 为什么两个相同的字符串在 if 条件下不匹配....?