Java 相同返回类型的多个Jackson序列化程序
我使用Jackson进行JSON序列化,并编写了两个自定义的Java 相同返回类型的多个Jackson序列化程序,java,json,jackson,Java,Json,Jackson,我使用Jackson进行JSON序列化,并编写了两个自定义的String序列化程序,一个类的每个getter方法都有一个序列化程序。每个方法都返回相同的类型,Set,但每个方法使用不同的序列化程序 不幸的是,Jackson并没有使用每个序列化程序,每个方法使用一个序列化程序,而是两个方法都使用一个序列化程序。它似乎接受按字母顺序排在第一位的任何方法,并对这两个方法使用其序列化程序。我期望第一个方法上注释的序列化程序用于第一个方法,第二个方法上注释的序列化程序用于第二个方法。调试似乎表明Jacks
String
序列化程序,一个类的每个getter方法都有一个序列化程序。每个方法都返回相同的类型,Set
,但每个方法使用不同的序列化程序
不幸的是,Jackson并没有使用每个序列化程序,每个方法使用一个序列化程序,而是两个方法都使用一个序列化程序。它似乎接受按字母顺序排在第一位的任何方法,并对这两个方法使用其序列化程序。我期望第一个方法上注释的序列化程序用于第一个方法,第二个方法上注释的序列化程序用于第二个方法。调试似乎表明Jackson在一个映射中有序列化程序,该映射由方法的返回类型设置了键(这两种方法都是相同的)
例如:
公共类FooBar{
私有集foos=newhashset();
private Set bar=new HashSet();
@JsonProperty(“FooWrapper”)
@JsonSerialize(contentUsing=FooSerializer.class)
公共集getFoos(){
返回foos;
}
@JsonProperty(“BarWrapper”)
@JsonSerialize(contentUsing=BarSerializer.class)
公共设置getbar(){
返回杆;
}
}
关于如何让getFoos()
方法使用FooSerializer
进行序列化,以及如何让getbar()
方法使用BarSerializer
进行序列化,有何建议?在本例中,这两种方法都调用了BarSerializer
注意,如果我将其中一个方法的签名更改为另一个集合类型,使它们不同-List
,例如,序列化可以工作
提前感谢。我认为在1.9.xx版中,如果将
对象映射器
与@JsonSerialize(contentUsing=BarSerializer.class)
结合使用,您想要实现的目标是不可能的
Jackson确实缓存了序列化程序,它基于与序列化程序关联的JavaType
(在本例中为Set
)缓存它们。看
虽然BeanProperty
被传递给此方法,但它不作为缓存键的一部分使用。在缓存值序列化程序时,可以将StdSerializerProvider
子类化,并考虑BeanProperty
参数,但这可能不是解决问题的最简单方法
快速修复方法是使用@JsonSerialize(using=FooCollectionSerializer.class)
并自行处理集合的序列化。通过执行此操作,序列化程序将成为用于序列化属性的BeanPropertyWriter
。使用@JsonSerialize(contentUsing=BarSerializer.class)
时,没有任何序列化程序耦合到BeanPropertyWriter
,该序列化程序触发基于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();
}
}
}
公共类FooBar{
私有集foos=newhashset();
private Set bar=new HashSet();
@JsonProperty(“FooWrapper”)
@JsonSerialize(使用=FooCollectionSerializer.class)
公共集getFoos(){
返回foos;
}
@JsonProperty(“BarWrapper”)
@JsonSerialize(使用=BarCollectionSerializer.class)
公共设置getbar(){
返回杆;
}
公共静态类FooCollectionSerializer扩展了JsonSerializer{
JsonSerializer序列化程序;
公共食品收集序列化程序(){
//让Jackson处理序列化集合的问题,只需指定序列化单个项的方式
this.serializer=new StringCollectionSerializer(null,new FooSerializer());
}
@凌驾
public void serialize(集合值、JsonGenerator jgen、SerializerProvider提供程序)引发IOException、JsonProcessingException{
serializer.serialize(值、jgen、提供程序);
}
}
公共静态类FooSerializer扩展SerializerBase{
公共序列化程序(){
super(String.class);
}
@凌驾
公共void序列化(字符串值、JsonGenerator jgen、SerializerProvider提供程序)引发IOException{
jgen.writeString(值);
}
}
公共静态类BarCollectionSerializer扩展了JsonSerializer{
@凌驾
public void serialize(集合值、JsonGenerator jgen、SerializerProvider提供程序)引发IOException、JsonProcessingException{
//自己处理序列化集合
jgen.writestarray();
for(字符串值:值){
jgen.writeString(值);
}
jgen.writeEndArray();
}
}
}
我们可以知道您正在使用的Jackson版本吗?我已经在Jackson(org.codehaus.Jackson)1.9.11中检查过这种行为,但它不起作用。在此之后,我将Jackson库更新为2.2.2版(com.fasterxml.Jackson),效果非常好。你能在你的项目中升级Jackson库吗?我想我不能,因为另一个使用Jackson的工具我最终升级到了Jackson 2.x,一切都很好。谢谢。我最终升级到了Jackson 2,这需要我将另一个工具(Spring Integration)升级到一个非官方版本,但一切正常。我奖励你一笔赏金,因为你提供了一个获得杰克逊的详细例子
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();
}
}
}