杰克逊:将枚举序列化为接口

时间:2013-05-08 14:41:46

标签: java json serialization jackson

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

假设我有两个系统,Producer和Consumer。除了单个共享接口外,它们的代码完全独立:

public interface Thing {
    String getName();
    String getDescription();
    int getPrice();
}

这个想法是Producer创建了一堆数据并通过HTTP将其作为JSON发送。 Producer有很多Thing的实现,每个都有额外的元数据和数据生成过程中所需的东西。

因为除了最顶层的薄层之外,生产者不需要任何杰克逊/序列化知识,所以序列化属性应该保留在Thing实现之外。由于将来很可能会增加实施的数量,因此对所有这些实施的混合使用很快就变得不可持续。据信将注释应用于Thing接口本身就足够了。

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

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

@JsonFormat(shape= JsonFormat.Shape.OBJECT)

虽然确实通过序列化字段而不是名称来解决问题,但它也 ,因为它也开始序列化未在Thing界面中定义的特定于实现的公共字段,从而产生由于包含未知条目的数据,不仅信息泄漏,而且消费者的反序列化失败。

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

有没有办法,简单地通过改变界面本身及其注释,来强制确切地说那些字段,不再是,不能少,应该在类和枚举时被序列化?

2 个答案:

答案 0 :(得分:1)

当我和杰克逊合作时,我遇到了这个问题。反序列化失败是因为在反序列化期间,Jackson无法找到多态引用类型。

您应该使用@JsonTypeInfo注释您的界面。

类似的东西:

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

您的问题中没有太多代码,因此这个答案。

答案 1 :(得分:0)

通常你应该能够强制使用某种类型:

 @JsonSerialize(as=Thing.class)

@JsonDeserialize类似。 这不适用于枚举吗?