杰克逊反序列化多态类不是数组

时间:2016-04-14 19:01:52

标签: java json jackson polymorphism deserialization

我正在尝试将json反序列化为多态类的简单示例。反序列化失败,错误:

org.codehaus.jackson.map.JsonMappingException: Could not resolve type id 'aField' into a subtype of [simple type, class ...SubClassA]

如果我尝试对单个子类进行反序列化,只使用该类的JSON,它就会成功,但是当我将这两个类放在SubClassTestObject中时,它会失败。有什么想法解决这个问题?我是否需要编写自定义反序列化器?

这是我的JSON:

{
    "classA":{
        "aField":"A",
        "baseField":"baseA"
    },
    "classB":{
        "baseField":"baseB",
        "bField":"B"
    }
}

以下是我的课程:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
    @JsonSubTypes.Type(value = SubClassA.class, name = "classA"),
    @JsonSubTypes.Type(value = SubClassB.class, name = "classB")
})

@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AbstractSimpleClass {
    String baseField;

    public String getBaseField() {
        return baseField;
    }

    public void setBaseField(String baseField) {
        this.baseField = baseField;
    }
}

public class SubClassA extends AbstractSimpleClass {
    String aField;

    public String getaField() {
        return aField;
    }

    public void setaField(String aField) {
        this.aField = aField;
    }
}

public class SubClassB extends AbstractSimpleClass {
    String bField;

    public String getbField() {
        return bField;
    }

    public void setbField(String bField) {
        this.bField = bField;
    }

}
@JsonIgnoreProperties(ignoreUnknown = true)
public class SubClassTestObject {
    @JsonProperty("classA")
    SubClassA a;

    @JsonProperty("classB")
    SubClassB b;

    public SubClassA getA() {
        return a;
    }
    public void setA(SubClassA a) {
        this.a = a;
    }
    public SubClassB getB() {
        return b;
    }
    public void setB(SubClassB b) {
        this.b = b;
    }
}

这是我的测试:

@Test
public void testBoth() throws IOException, URISyntaxException {
    ClassLoader classLoader = getClass().getClassLoader();
    json = new String(Files.readAllBytes(Paths.get(classLoader.getResource("test/so-example.json").toURI())));
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerSubtypes(SubClassA.class, SubClassB.class);

    SubClassTestObject testObj = mapper.readValue(json, SubClassTestObject.class); //Fails here
    SubClassA a = testObj.getA();
    SubClassB b = testObj.getB();

    assertTrue(a.getBaseField().equals("baseA"));
    assertTrue(b.getBaseField().equals("baseB"));
    assertTrue(a.getaField().equals("A"));
    assertTrue(b.getbField().equals("B"));

}

1 个答案:

答案 0 :(得分:1)

编辑后:

@JsonProperty("classA")
SubClassA a;

完全无关
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)

JsonTypeInfo.As.WRAPPER_OBJECT意味着隐含。这不是您在POJO中映射的内容。您将无法使用此策略映射当前的JSON。例如,执行以下操作或更改JsonTypeInfo以使用JsonTypeInfo.As.PROPERTY,然后在JSON中提供相应的@type(及其相应的值)属性。

预编辑:

您的SubClassTestObject课程有两个属性,ab,因为

public SubClassA getA() {
    return a;
}
public SubClassB getB() {
    return b;
}

这些在您的JSON中不存在。既然你告诉杰克逊忽略了未知的属性,它就不会反序列化。但是,它们都将保持未初始化状态。

您要反序列化的JSON是

{
    "a": {
        "classA": {
            "aField": "A",
            "baseField": "baseA"
        }
    },
    "b": {
        "classB": {
            "baseField": "baseB",
            "bField": "B"
        }
    }
}

对您的根a对象有bSubClassTestObject。并且那些使用具有适当JsonTypeInfo名称的包装器对象。