java - 相同返回类型的多个 Jackson 序列化程序

标签 java json jackson

我正在使用 Jackson 进行 JSON 序列化并编写了一些自定义 String序列化器,一个类的每个 getter 方法。每个方法都返回相同的类型,Set<String> ,但每个都使用不同的序列化器。

不幸的是,Jackson 没有使用每个序列化器,每个方法一个,而是为两种方法使用一个序列化器。它似乎采用按字母顺序排在第一位的任何方法,并为这两种方法使用其序列化程序。我期望的是第一个方法上注释的序列化器用于第一个方法,第二个方法上注释的序列化器用于第二个方法。调试似乎表明 Jackson 在映射中有序列化程序,该映射由方法的返回类型键入(两者都相同)。

一个例子:

public class FooBar {

  private Set<String> foos = new HashSet<String>();
  private Set<String> bars = new HashSet<String>();

  @JsonProperty("FooWrapper")
  @JsonSerialize(contentUsing = FooSerializer.class)
  public Set<String> getFoos() {
    return foos;
  }

  @JsonProperty("BarWrapper")
  @JsonSerialize(contentUsing = BarSerializer.class)
  public Set<String> getBars() {
    return bars;
  }
}

关于如何获得 getFoos() 的任何建议用 FooSerializer 序列化的方法, 和 getBars()使用 BarSerializer 序列化的方法?在此示例中,BarSerializer为这两种方法调用。

请注意,如果我将其中一种方法的签名更改为另一种集合类型,那么它们就会不同 - List<String>例如 - 序列化有效。

提前致谢。

最佳答案

我认为当使用 ObjectMapper 时,您想要实现的目标在 1.9.xx 版中是不可能的。结合 @JsonSerialize(contentUsing = BarSerializer.class) .

Jackson 确实缓存了序列化程序,它根据 JavaType 缓存它们。 (在本例中为 Set<String> ) 与序列化程序相关联。参见 StdSerializerProvider.findValueSerializer(JavaType valueType, BeanProperty property) .

尽管 BeanProperty传递给此方法,它不用作缓存键的一部分。你可以继承 StdSerializerProvider并采取 BeanProperty缓存值序列化程序时考虑参数,但这可能不是解决问题的最简单方法。

快速解决方法是使用 @JsonSerialize(using = FooCollectionSerializer.class)并自己处理系列化。通过这样做,序列化器是 directly coupledBeanPropertyWriter用于序列化属性。使用 @JsonSerialize(contentUsing = BarSerializer.class)BeanPropertyWriter 没有耦合序列化器这会触发 serializer lookup缓存基于 JavaType 的序列化程序

public class FooBar {

    private Set<String> foos = new HashSet<>();
    private Set<String> bars = new HashSet<>();

    @JsonProperty("FooWrapper")
    @JsonSerialize(using = FooCollectionSerializer.class)
    public Set<String> getFoos() {
        return foos;
    }

    @JsonProperty("BarWrapper")
    @JsonSerialize(using = BarCollectionSerializer.class)
    public Set<String> getBars() {
        return bars;
    }

    public static class FooCollectionSerializer extends JsonSerializer<Collection<String>> {

        JsonSerializer<Collection<String>> 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<String> value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            serializer.serialize(value, jgen, provider);
        }
    }

    public static class FooSerializer extends SerializerBase<String> {
        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<Collection<String>> {

        @Override
        public void serialize(Collection<String> values, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            //handle serializing the collection yourself
            jgen.writeStartArray();
            for (String value : values) {
                jgen.writeString(value);

            }
            jgen.writeEndArray();
        }
    }
}

关于java - 相同返回类型的多个 Jackson 序列化程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20037695/

相关文章:

java - 如何从该方法中获取方法名称?

java - 创建 3D 程序的工具

javascript - $.getJSON() 不适用于 chrome

php - PHP MySQL JSON 中的 REST Web 服务 - 将空值插入数据库

jackson - 无法在 Spring Boot 应用程序中注入(inject)多个 ObjectMapper bean

java - 重写静态内部类的静态方法时出现 Stackoverflow 错误

java - Hibernate 在 columnDefinition 周围加上反引号

javascript - 过滤[空]数组对象

java - 使用 Jackson 将瞬间序列化为毫秒?

java - Jackson - 由于构造函数导致的 JsonMappingException