多个相同返回类型的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(); } } }