【发布时间】:2013-05-08 14:41:46
【问题描述】:
(免责声明:过于简单化。实际情况要复杂得多。)
假设我有两个系统,生产者和消费者。他们的代码是完全独立的,除了一个共享接口:
public interface Thing {
String getName();
String getDescription();
int getPrice();
}
这个想法是生产者创建一堆数据并通过 HTTP 将其作为 JSON 发送。 Producer 有一堆 Thing 的实现,每一个都有额外的元数据和数据生成过程所需的东西。
由于 Producer 不希望拥有任何关于 Jackson/序列化的知识,除了最顶层的薄层之外,序列化属性应该被排除在 Thing 实现之外。由于未来实施的数量很可能会增长,因此为所有这些实施混合很快就会变得不可持续。将注释应用到 Thing 接口本身就足够了。
第一个简单的方法是在接口上添加@JsonSerialize 注解。起初,这似乎可行,但导致了一个问题。 Thing 的一些实现是枚举,导致 Jackson 只是将它们序列化为它们的名称,而不是接口中定义的字段。
一些谷歌搜索显示以下注释:
@JsonFormat(shape= JsonFormat.Shape.OBJECT)
虽然它确实通过序列化字段而不是名称来解决问题,但它也做得很好,因为它还开始序列化未在 Thing 接口中定义的特定于实现的公共字段,结果不仅是信息泄露,还有Consumer反序列化失败,因为数据包含未知条目。
由于进一步的谷歌搜索没有产生任何结果,我能想到的唯一解决方案是将所有这些字段标记为可忽略,由于前面提到的原因,这是非常不可取的。
有没有什么办法,只要改变接口本身和它的注释,就可以强制那些字段在涉及到类和枚举时都应该被序列化,不多也不少?
【问题讨论】:
-
你不能不使用枚举而使用普通类吗?
-
@reverse_engineer 理论上是的。但是,将一些实现作为枚举极大地简化了 Producer,原因有多种,我不会详细介绍。用类替换它们并不是一个真正的选择。
-
您可能仍需要@JsonFormat,但fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/… 是另一种指示可能有效的序列化类型的方法。比如mapper.writerFor(Thing.class).writeValue...
标签: java json serialization jackson