Java Jackson:将枚举序列化为接口

Java Jackson:将枚举序列化为接口,java,json,serialization,jackson,Java,Json,Serialization,Jackson,(免责声明:极度简化。实际情况要复杂得多。) 假设我有两个系统,生产者和消费者。除了一个共享接口之外,它们的代码是完全独立的: public interface Thing { String getName(); String getDescription(); int getPrice(); } 其思想是生产者创建一组数据并通过HTTP将其作为JSON发送。Producer有一系列的东西实现,每个都有额外的元数据和数据生成过程中需要的东西 由于制作人除了最顶层的薄层之

(免责声明:极度简化。实际情况要复杂得多。)

假设我有两个系统,生产者和消费者。除了一个共享接口之外,它们的代码是完全独立的:

public interface Thing {
    String getName();
    String getDescription();
    int getPrice();
}
其思想是生产者创建一组数据并通过HTTP将其作为JSON发送。Producer有一系列的东西实现,每个都有额外的元数据和数据生成过程中需要的东西

由于制作人除了最顶层的薄层之外,不希望了解任何类型的Jackson/序列化知识,所以序列化属性应该被排除在实现之外。由于实现的数量在未来很可能会增加,因此将所有实现混合在一起很快变得不可持续。人们认为,将注释应用于Thing接口本身就足够了

第一种简单的方法是在接口上使用@JsonSerialize注释。起初,这似乎是可行的,但最终导致了一个问题。Thing的一些实现是枚举,这导致Jackson只是将它们序列化为它们的名称,而不是接口中定义的字段

一些谷歌搜索显示了以下注释:

@JsonFormat(shape= JsonFormat.Shape.OBJECT)
虽然它确实通过序列化字段而不是名称来解决问题,但它做得太好了,因为它还开始序列化Thing接口中未定义的特定于实现的公共字段,这不仅导致信息泄漏,而且由于数据包含未知条目,导致消费者中的反序列化失败

由于进一步的谷歌搜索没有产生任何结果,我能想到的唯一解决办法是将所有这些字段标记为可忽略的,由于前面提到的原因,这是非常不可取的


有没有办法,只要改变接口本身及其注释,就可以强制执行这些字段,无论是在类还是枚举中,都应该被序列化?

我在与Jackson合作时遇到了这个问题。反序列化失败,因为在反序列化过程中,Jackson无法找到多态引用类型

您应该使用@JsonTypeInfo注释您的接口

比如:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")

你的问题中没有太多的代码,因此答案是这样的

通常,您应该能够通过以下方式强制使用某些类型:

 @JsonSerialize(as=Thing.class)
@JsonDeserialize类似。

这对枚举不起作用吗?

你就不能不使用枚举而改用普通类吗?@reverse\u理论上是的。然而,由于各种原因,将一些实现作为枚举大大简化了生产者,我将不详细介绍。用类替换它们并不是一个真正的选项。您可能仍然需要@JsonFormat,但这是另一种指示序列化类型的方法,可能会起作用。例如,mapper.writerFor(Thing.class).writeValue…多态性在本例中不是问题。消费者不关心这个类最初是什么;它只是将数据反序列化为实现Thing接口的类bean。问题是它序列化太多,而不是太少。