Java 用Jackson反序列化派生类

Java 用Jackson反序列化派生类,java,inheritance,jackson,deserialization,Java,Inheritance,Jackson,Deserialization,我有两个自动生成的类,如下所示: public class DataMonitoringClauseType extends ClauseType { } public class ClauseType { } public class RootClass { List<ClauseType> clauses; } 由于这些类是自动生成的,我无法为它们定义额外的注释,如JsonSubType 我有第三个对象,它有一个子句类型列表,如下所示: public class D

我有两个自动生成的类,如下所示:

public class DataMonitoringClauseType extends ClauseType {
}

public class ClauseType {
}
public class RootClass {
    List<ClauseType> clauses;
}
由于这些类是自动生成的,我无法为它们定义额外的注释,如
JsonSubType

我有第三个对象,它有一个子句类型列表,如下所示:

public class DataMonitoringClauseType extends ClauseType {
}

public class ClauseType {
}
public class RootClass {
    List<ClauseType> clauses;
}

请注意,序列化的内容作为输入传递给服务器。因此,我没有机会在序列化内容中包含类型信息。

对于Jackson,您可以为
子句类型定义自定义反序列化器

class ClauseTypeDeserializer extends StdDeserializer<DataMonitoringClauseType> {

    @Override
    public DataMonitoringClauseType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        // get data, e.g.: data = jp.getCodec().readTree(jp).toString().getBytes();
        // construct result:
        return new DataMonitoringClauseType(data)
    }
}
如果您对Gson感兴趣,解决方案非常类似:

class ClauseTypeDeserializer implements JsonDeserializer<ClauseType> {

    @Override
    public ClauseType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // get data, e.g.: data = jpson.toString().getBytes();
        // construct result:
        return new DataMonitoringClauseType(data)
    }
}

不需要使用自定义反序列化程序 不需要自定义反序列化程序或Gson。杰克逊提供了两种方法

第一:不能直接修改类并不意味着不能使用Jackson注释:这正是“mix-in”注释的使用案例。例如,请参阅关于如何使用混合插件的示例,这样您就可以使用

@JsonDeserialize(as=DataMonitoringClauseType.class)
public class ClauseType { .... }
或者,您也可以注册实现类型(您注册子类型的尝试适用于多态子类型,其中使用了类型id——但我认为这不是您想要的)。 这是使用
模块
接口,方法“addAbstractTypeMapping()”完成的


我对否决票感到困惑,没有任何评论,因为我实际上可以提供一个github链接,指向生产代码中使用的上述两个示例,这两个示例正是问题所在。不管怎么说,有些人很奇怪,这是生活中的事实。谢谢奥列格!我只是在尝试同样的解决方案,却不知道如何访问“数据”。现在,我得到了它,它的工作!我认为,在有文字单行解决方案的情况下,编写自定义(反)序列化程序是一种浪费。我建议不要这样做,除非没有其他方法。@StaxMan现在如果你说使用类型适配器工厂将一种类型映射到另一种类型,而不编写客户反序列化程序,我会同意,即使上面的答案是通用的。如果您的建议是使用注释,我强烈反对:我的DTO模块既不应该依赖于特定的序列化(注释)库,也不应该让DTO知道如何使用它。@OlegSklyar直接添加注释是一种方法——您可以随意不喜欢这一部分,有些开发人员喜欢,有些开发人员不喜欢,这是一个有效的讨论。但这不是唯一的办法。我确实意识到你没有意识到其他选择,从这个意义上说,你的建议是一个有效的解决方案。至于不必知道的DTO,那。。。是更大讨论的一部分,这取决于上下文。自定义反序列化程序的使用更简洁,因为DTO与序列化技术分离。我知道有些人喜欢注释,但这并不能使他们变得更好。谢谢!我不想添加额外的类,因为我们已经有了一个大型数据模型。然而,我正在寻找第二种选择。“我会试试看。”斯塔克斯曼这里有一些近乎哲学的问题和方法上的差异,因此不是讨论它们的好地方:)我既不喜欢也不讨厌注释,我真的看不出它们有什么功能。但我不喜欢滥用注释来解决任何可能出现的问题(想想EE、JPA、servlet等等)。至于JSON序列化,到目前为止,我在没有注释的情况下以最小的开销解决了所有问题,而且我现在已经解决了很多问题。@OlegSklyar同意wrt的理念/设计,并且这不是一个好论坛(也没有真正的答案)。我同意注释可能被过度使用,并且存在权衡,特别是在“错误方向”链接的情况下(比如这里)。我就到此为止,只是要注意,我的第二个建议不是注释一,我可能应该提到这是我的第一个建议,而不是注释。感谢这里的讨论,因为它是分析和理性的;如果我误解了你的观点,我深表歉意。@StaxMan将是一个很好的功能,因此可以自动在某个专门的讨论室中继续。我发现这些交流对于获得更好的见解非常有价值。也谢谢你!
@JsonDeserialize(as=DataMonitoringClauseType.class)
public class ClauseType { .... }