多个相同返回类型的Jackson序列化器 [英] Multiple Jackson Serializers of Same Return Type

查看:229
本文介绍了多个相同返回类型的Jackson序列化器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Jackson for JSON serialization and have written a couple custom String serializers, one for each getter method of a class. The methods each return the same type, Set<String>, but each uses a different serializer.

不幸的是, Jackson没有使用每个序列化程序,每个方法一个,但是两个都使用一个序列化程序。它似乎采用按字母顺序排列的任何方法,并将其序列化器用于这两种方法。我期望的是第一种方法注释的序列化器用于第一种方法,第二种方法注释的序列化器用于第二种方法。调试似乎表明杰克逊在地图中的序列化器具有方法的返回类型(两者都相同)。

Unfortunately, Jackson is not using each serializer, one for each method, but is using one serializer for both. It appears to take whatever method comes first alphabetically and uses its serializer for both methods. What I expect is that the serializer annotated on the first method is used for the first method, and the serializer annotated on the second method is used on the second method. Debugging appears to indicate that Jackson has the serializers in a map keyed by return type of the method (which is the same for both).

示例:

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;
  }
}

有关如何获得<$ c $的任何建议c> getFoos()使用 FooSerializer 进行序列化的方法,以及 getBars()使用 BarSerializer 序列化的方法?在此示例中,为两种方法调用 BarSerializer

Any suggestions on how to get the getFoos() method to serialize with a FooSerializer, and the getBars() method to serialize with the BarSerializer? In this example, the BarSerializer is invoked for both methods.

注意,如果我更改其中一个方法的签名另一个集合类型的方法,因此它们是不同的 - 列表< String> 例如 - 序列化工作。

Note, if I change the signature of one of the methods to another collection type so they are different - List<String> for example - the serialization works.

在此先感谢。

推荐答案

我认为在使用<1.xxx版本时,您尝试实现的目标是不可能的code> ObjectMapper 与 @JsonSerialize(contentUsing = BarSerializer.class)组合使用。

I think what you are trying to achieve isn't possible in version 1.9.xx when using an ObjectMapper in combination with @JsonSerialize(contentUsing = BarSerializer.class).

Jackson确实缓存了序列化程序,并根据 JavaType 缓存它们(在这种情况下) 设置< String> 与序列化程序相关联。参见 StdSerializerProvider.findValueSerializer(JavaType valueType,BeanProperty property)

Jackson does indeed cache the serializers, and it caches them based on the JavaType (in this case Set<String>) that's associated with the serializer. See StdSerializerProvider.findValueSerializer(JavaType valueType, BeanProperty property).

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

Although the BeanProperty is passed to this method, it isn't used as part of the cache key. You could subclass StdSerializerProvider and take the BeanProperty parameter into account when caching value serializers, but that's probably not the easiest way to solve your problem.

快速解决方法是使用 @JsonSerialize(using = FooCollectionSerializer.class)和处理自己序列化的集合。通过这样做,序列化器直接耦合到用于序列化属性的 BeanPropertyWriter 。当使用 @JsonSerialize(contentUsing = BarSerializer.class)时,没有序列化器连接到 BeanPropertyWriter ,这会触发序列化程序查找,根据缓存序列化程序JavaType

As a quick fix would be to use @JsonSerialize(using = FooCollectionSerializer.class) and deal with serializing the collection yourself. By doing this, the serializer is directly coupled to the BeanPropertyWriter used to serialize the property. When using @JsonSerialize(contentUsing = BarSerializer.class) there's no serializer coupled to the BeanPropertyWriter which triggers the serializer lookup that caches the serializers based on the 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();
        }
    }
}

这篇关于多个相同返回类型的Jackson序列化器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆