Jackson JSON针对某些领域的自定义序列化

Ste*_*Kuo 85 java serialization json jackson

有没有办法使用Jackson JSON处理器进行自定义字段级序列化?例如,我想要上课

public class Person {
    public String name;
    public int age;
    public int favoriteNumber;
}
Run Code Online (Sandbox Code Playgroud)

序列化为以下JSON:

{ "name": "Joe", "age": 25, "favoriteNumber": "123" }
Run Code Online (Sandbox Code Playgroud)

注意,age = 25被编码为数字而favoriteNumber = 123被编码为字符串.开箱即用杰克逊编组int了一个号码.在这种情况下,我希望favoriteNumber被编码为字符串.

Kev*_*sox 95

您可以按如下方式实现自定义序列化程序:

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = IntToStringSerializer.class, as=String.class)
    public int favoriteNumber:
}


public class IntToStringSerializer extends JsonSerializer<Integer> {

    @Override
    public void serialize(Integer tmpInt, 
                          JsonGenerator jsonGenerator, 
                          SerializerProvider serializerProvider) 
                          throws IOException, JsonProcessingException {
        jsonGenerator.writeObject(tmpInt.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

Java的应该处理自动装箱int给Integer你.

  • 注意`as = String.class`由于`using`参数而被忽略,这里不需要.[*注意:如果也使用using(),它具有优先权(因为它直接指定了序列化程序,而这只会用于定位序列化程序),并且忽略此注释属性的值.*](http:// jackson. codehaus.org/1.7.0/javadoc/org/codehaus/jackson/map/annotate/JsonSerialize.html#as()) (4认同)
  • Jackson-databind(至少2.1.3)已经包含特殊的ToStringSerializer,请参阅我的回答. (2认同)

wer*_*okz 52

Jackson-databind(至少2.1.3)提供特殊ToStringSerializer(com.fasterxml.jackson.databind.ser.std.ToStringSerializer)

例:

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = ToStringSerializer.class)
    public int favoriteNumber:
}
Run Code Online (Sandbox Code Playgroud)

  • String 需要转换为 int 的反向怎么样?我没有看到 ToIntSerializer.class。 (3认同)

Joã*_*lva 11

添加带@JsonProperty注释的getter,String为该favoriteNumber字段返回a :

public class Person {
    public String name;
    public int age;
    private int favoriteNumber;

    public Person(String name, int age, int favoriteNumber) {
        this.name = name;
        this.age = age;
        this.favoriteNumber = favoriteNumber;
    }

    @JsonProperty
    public String getFavoriteNumber() {
        return String.valueOf(favoriteNumber);
    }

    public static void main(String... args) throws Exception {
        Person p = new Person("Joe", 25, 123);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(p)); 
        // {"name":"Joe","age":25,"favoriteNumber":"123"}
    }
}
Run Code Online (Sandbox Code Playgroud)


Igo*_* G. 11

如果您不想使用注释污染模型并希望执行一些自定义操作,则可以使用 mixins。

ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.setMixInAnnotation(Person.class, PersonMixin.class);
mapper.registerModule(simpleModule);
Run Code Online (Sandbox Code Playgroud)

覆盖年龄:

public abstract class PersonMixin {
    @JsonSerialize(using = PersonAgeSerializer.class)
    public String age;
}
Run Code Online (Sandbox Code Playgroud)

做任何你需要的年龄:

public class PersonAgeSerializer extends JsonSerializer<Integer> {
    @Override
    public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(String.valueOf(integer * 52) + " months");
    }
}
Run Code Online (Sandbox Code Playgroud)


Ole*_*hin 10

jackson-annotations提供了@JsonFormat可以处理大量自定义而无需编写自定义序列化程序的方法.

例如,STRING为具有数字类型的字段请求形状将输出数值作为字符串

public class Person {
    public String name;
    public int age;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    public int favoriteNumber;
}
Run Code Online (Sandbox Code Playgroud)

将产生所需的输出

{"name":"Joe","age":25,"favoriteNumber":"123"}
Run Code Online (Sandbox Code Playgroud)