【问题标题】:Using Jackson to / from JSON where each class implements the same interface使用 Jackson 到/来自 JSON,其中每个类都实现相同的接口
【发布时间】:2015-10-15 08:32:45
【问题描述】:

我正在尝试使用 Jackson 反序列化一个相当复杂的 JSON 结构。

序列化工作正常:

参数接口:

public interface Param<T> {
}

不是.java:

public class Not implements Param<Param<?>> {

    private Param not;

    public Not(){

    }

    public Not(Param not) {
        this.not = not;
    }

    public Param getNot() {
        return not;
    }

}

And.java:

public class And implements Param<List<?>> {

    private List<Param> and;

    public List<Param> getAnd() {
        return and;
    }

    public List<Param> add(Param ... params){
        for (Param param : params){
            this.and.add(param);
        }
        return this.and;
    }

    public And() {
        this.and = new ArrayList<>();
    }

    public And(Param ... params){
        this.and = new ArrayList<>();
        for (Param param : params){
            this.and.add(param);
        }
    }

}

公司.java:

public class CompanyName implements Param<String> {

    private String companyName;

    public CompanyName(String value) {
        this.companyName = value;
    }

    public String getCompanyName() {
        return companyName;
    }
}

序列化:

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new And(new Or(new CompanyName("ABC"), new CompanyName("DEF")), new Not(new CompanyName("GHI")))));

打印:

{"and":[{"or":[{"companyName":"ABC"},{"companyName":"DEF"}]},{"not":{"companyName":"GHI"}}]}

现在反序列化,Jackson 怎么知道如何映射和/或/companyName/不回他们的对象?

And and = mapper.readValue(json, And.class);

线程“main”中的异常 com.fasterxml.jackson.databind.JsonMappingException:无法构造 com.ahp.messaging.param.Param 的实例,问题:抽象类型 要么需要映射到具体类型,要么有自定义反序列化器, 或在 [Source: {"and":[{"or":[{"companyName":"ABC"},{"companyName":"DEF"}]},{"not":{"companyName":"GHI"}}] }; 行:1,列:9](通过参考链: com.ahp.messaging.param.And["and"]->java.util.ArrayList[0])

为了摆脱这个异常,我修改了Param接口如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "T", visible = false)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Not.class, name = "not"),
    @JsonSubTypes.Type(value = And.class, name = "and"),
    @JsonSubTypes.Type(value = Or.class, name = "or"),
    @JsonSubTypes.Type(value = CompanyName.class, name = "companyName")

})
public interface Param<T> {

}

现在它序列化为:

{"T":"and","and":[{"T":"or","or":[{"T":"companyName","companyName":"ABC"},{"T":"companyName","companyName":"DEF"}]},{"T":"not","not":{"T":"companyName","companyName":"GHI"}}]}

完美反序列化,但所有内容都有类型信息,有没有办法摆脱类型信息,只在真正需要的地方使用?

【问题讨论】:

  • 你的意思是 T 在根?所有其他的似乎都是必要的。
  • 我宁愿摆脱所有这些,但这可能需要一个我以前从未做过的自定义反序列化器。因此,如果它们都是必需的,那么我将接受一个可以使用自定义解串器朝着正确方向前进的样本作为正确答案。

标签: java json serialization jackson deserialization


【解决方案1】:

简答,需要类型信息。

使用 XML,您可以获得每个元素的类型信息,使用 JSON,您会牺牲类型信息以获得更小的表示,但在这种情况下,废弃类型信息意味着无法推断它应该映射到哪个类。

【讨论】:

    猜你喜欢
    • 2019-03-29
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 2022-08-18
    相关资源
    最近更新 更多