【问题标题】:Jackson Deserialize Polymorphic Classes not as Array杰克逊反序列化多态类而不是数组
【发布时间】:2016-04-14 19:01:51
【问题描述】:

我正在尝试做一个将 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"));

}

【问题讨论】:

  • 更新问题...
  • 以后,请在发布问题前检查您的问题。这是一个非常不同的场景。
  • 我的错,在看到第一个答案后,我看到了其中一个问题,所以我修复了它,它变成了另一个问题。
  • 您想在SubClassTestObject 中使用类型信息吗?还是碰巧您只有这样的类,并且您确切知道 SubClassTestObject { SubClassA a; 中期望的类型是什么? SubClassB b;} 因为你可以把@JsonTypeInfo(use=JsonTypeInfo.Id.NONE) 放在SubClassASubClassB 上面,这段代码对你有用
  • 您只能更改 public class SubClassTestObject { @JsonProperty("classA") @JsonTypeInfo(use=JsonTypeInfo.Id.NONE) SubClassA a; @JsonProperty("classB") @JsonTypeInfo(use=JsonTypeInfo.Id.NONE) SubClassB b;} 并且您提供的其余代码都可以使用,但是您根本不需要输入信息

标签: java json jackson polymorphism deserialization


【解决方案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"
        }
    }
}

其中有 ab 用于您的根 SubClassTestObject 对象。而那些使用具有适当 JsonTypeInfo 名称的包装器对象。

【讨论】:

  • 嗯,好吧,我必须保持 json 不变。我正在更新我的问题。
  • 是否可以在不更改 JSON 的情况下实现?我正在做这个简单的练习案例,但在我的项目中,我必须以它当前的格式处理 JSON。看起来我唯一的选择可能是为 SubClassTestObject 编写一个自定义反序列化器。跨度>
  • @PunDefeated 使用您当前的 JSON,不,我看不到 JsonTypeInfo 的明确方式。
  • 好的,谢谢。我接受你的回答,因为它表明这是不可能的,这肯定是一个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
相关资源
最近更新 更多