多个相同返回类型的Jackson序列化器
我正在使用Jackson进行JSON序列化,并编写了一些自定义String
序列化程序,一个用于类的每个getter方法。 每个方法返回相同的类型Set
,但每个都使用不同的序列化程序。
不幸的是,jackson没有使用每个序列化器,每个方法一个,但两个都使用一个序列化器。 它似乎采用按字母顺序排列的任何方法,并将其序列化器用于这两种方法。 我期望的是第一种方法注释的序列化器用于第一种方法,第二种方法注释的序列化器用于第二种方法。 调试似乎表明Jackson在地图中的序列化器中键入了方法的返回类型(两者都相同)。
一个例子:
public class FooBar { private Set foos = new HashSet(); private Set bars = new HashSet(); @JsonProperty("FooWrapper") @JsonSerialize(contentUsing = FooSerializer.class) public Set getFoos() { return foos; } @JsonProperty("BarWrapper") @JsonSerialize(contentUsing = BarSerializer.class) public Set getBars() { return bars; } }
有关如何使用getFoos()
获取getFoos()
方法序列化以及使用FooSerializer
序列化的getFoos()
方法的任何建议? 在此示例中,将为两种方法调用BarSerializer
。
注意,如果我将其中一个方法的签名更改为另一个集合类型,以便它们不同 – 例如List
– 序列化工作。
提前致谢。
我认为当将ObjectMapper
与@JsonSerialize(contentUsing = BarSerializer.class)
结合使用时,您在1.9.xx版本中无法实现的目标。
Jackson确实缓存了序列化程序,并根据与序列化程序关联的JavaType
(在本例中为Set
)来缓存它们。 请参见StdSerializerProvider.findValueSerializer(JavaType valueType, BeanProperty property)
。
虽然BeanProperty
传递给此方法,但它不会用作缓存键的一部分。 您可以StdSerializerProvider
并在缓存值序列化器时考虑BeanProperty
参数,但这可能不是解决问题的最简单方法。
快速解决方法是使用@JsonSerialize(using = FooCollectionSerializer.class)
并@JsonSerialize(using = FooCollectionSerializer.class)
处理序列化集合。 通过这样做,序列化程序直接耦合到用于序列化属性的BeanPropertyWriter
。 当使用@JsonSerialize(contentUsing = BarSerializer.class)
,没有与BeanPropertyWriter
耦合的序列化程序触发序列化程序查找 ,该查找根据JavaType
高速缓存序列化JavaType
public class FooBar { private Set foos = new HashSet<>(); private Set bars = new HashSet<>(); @JsonProperty("FooWrapper") @JsonSerialize(using = FooCollectionSerializer.class) public Set getFoos() { return foos; } @JsonProperty("BarWrapper") @JsonSerialize(using = BarCollectionSerializer.class) public Set getBars() { return bars; } public static class FooCollectionSerializer extends JsonSerializer> { JsonSerializer> serializer; public FooCollectionSerializer() { //let Jackson deal with serializing the collection and just specify how you want to serialize indivial items this.serializer = new StringCollectionSerializer(null, new FooSerializer()); } @Override public void serialize(Collection value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { serializer.serialize(value, jgen, provider); } } public static class FooSerializer extends SerializerBase { public FooSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString(value); } } public static class BarCollectionSerializer extends JsonSerializer> { @Override public void serialize(Collection values, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { //handle serializing the collection yourself jgen.writeStartArray(); for (String value : values) { jgen.writeString(value); } jgen.writeEndArray(); } } }