共计 6233 个字符,预计需要花费 16 分钟才能阅读完成。
一、 Read+Write注解
Jackson包含一组注解,这些注解会影响从 JSON 读取 Java 对象以及将 Java 对象写入 JSON,这些称为 Read + Write 注解。
1. @JsonIgnore
@JsonIgnore 用于告诉 Jackson 忽略 Java 对象的某个属性(字段)。 在将 JSON 读取到 Java 对象中以及将 Java 对象写入 JSON 时,都将忽略该属性。
public class PersonIgnore {
@JsonIgnore
public long personId = 0;
public String name = null;
}
在上面的类中,不会从 JSON 读取或写入 JSON 属性 personId。
2. @JsonIgnoreProperties
@JsonIgnoreProperties 注解用于指定要忽略的类的属性列表。 @JsonIgnoreProperties注解放置在类声明上方,而不是要忽略的各个属性(字段)上方。
@JsonIgnoreProperties({"firstName", "lastName"})
public class PersonIgnoreProperties {
public long personId = 0;
public String firstName = null;
public String lastName = null;
}
属性 firstName 和 lastName 都将被忽略,因为它们的名称在类声明上方的@JsonIgnoreProperties 注解声明内列出。
3. @JsonIgnoreType
@JsonIgnoreType 注解用于将整个类型(类)标记为在使用该类型的任何地方都将被忽略。
public class PersonIgnoreType {
@JsonIgnoreType
public static class Address {
public String streetName = null;
public String houseNumber = null;
public String zipCode = null;
public String city = null;
public String country = null;
}
public long personId = 0;
public String name = null;
public Address address = null;
}
所有 Address 实例将被忽略。
4. @JsonAutoDetect
@JsonAutoDetect 用于告诉 Jackson 在读写对象时包括非 public 修饰的属性。
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY )
public class PersonAutoDetect {
private long personId = 123;
public String name = null;
}
JsonAutoDetect.Visibility 类包含与 Java 中的可见性级别匹配的常量,表示 ANY,DEFAULT,NON_PRIVATE,NONE,PROTECTED_AND_PRIVATE 和 PUBLIC_ONLY。
二、 Read注解
Jackson 包含一组注解,这些注解仅影响 Jackson 将 JSON 解析为对象的方式-意味着它们影响 Jackson 对 JSON 的读取。
1. @JsonSetter
@JsonSetter 用于告诉 Jackson,当将 JSON 读入对象时,应将此 setter 方法的名称与 JSON 数据中的属性名称匹配。 如果 Java 类内部使用的属性名称与 JSON 文件中使用的属性名称不同,这个注解就很有用了。
例如 json 数据为:
{
"id" : 1234,
"name" : "John"
}
对应的 java 对象:
public class Person {
private long personId = 0;
private String name = null;
public long getPersonId() { return this.personId; }
@JsonSetter("id")
public void setPersonId(long personId) { this.personId = personId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
默认情况下,Jackson 无法将 id 属性从 JSON 对象映射到 Java 类的 personId 字段,所以需要使用 JsonSetter 注解指定注入 id 属性。
2. @JsonAnySetter
@JsonAnySetter 表示 Jackson 为 JSON 对象中所有无法识别的字段调用相同的 setter 方法。 无法识别是指尚未映射到 Java 对象中的属性或设置方法的所有字段。
现有如下 java 对象:
public class Bag {
private Map<String, Object> properties = new HashMap<>();
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
需要接受的 json 数据为:
{
"id" : 1234,
"name" : "John"
}
Jackson 无法直接将此 JSON 对象的 id 和 name 属性映射到 Bag 类,因为 Bag 类不包含任何公共字段或 setter 方法。
可以通过添加@JsonAnySetter 注解来告诉 Jackson 为所有无法识别的字段调用 set()方法,如下所示:
public class Bag {
private Map<String, Object> properties = new HashMap<>();
@JsonAnySetter
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
3. @JsonCreator
@JsonCreator 用于告诉 Jackson 该 Java 对象具有一个构造函数(“创建者”),该构造函数可以将 JSON 对象的字段与 Java 对象的字段进行匹配。
@JsonCreator 注解在无法使用 @JsonSetter 注解的情况下很有用。 例如,不可变对象没有任何设置方法,因此它们需要将其初始值注入到构造函数中。
public class PersonImmutable {
private long id = 0;
private String name = null;
@JsonCreator
public PersonImmutable(
@JsonProperty("id") long id,
@JsonProperty("name") String name ) {
this.id = id;
this.name = name;
}
}
但是,仅凭在构造函数中添加 @JsonCreator 注解还不够。 还必须注解构造函数的参数,以告诉 Jackson 将 JSON 对象中的哪些字段传递给哪些构造函数参数。
所以在这种情况下,即使没有 set 方法也能够通过构造方法将如下 json 解析为 java 对象。
{
"id" : 1234,
"name" : "John"
}
4. @JsonDeserialize
注解 @JsonDeserialize 用于为 Java 对象中给定的属性指定自定义反序列化器类。
例如,假设想优化布尔值 false 和 true 的在线格式,使其分别为 0 和 1。
public class PersonDeserialize {
public long id = 0;
public String name = null;
@JsonDeserialize(using = OptimizedBooleanDeserializer.class)
public boolean enabled = false;
}
OptimizedBooleanDeserializer 类如下:
public class OptimizedBooleanDeserializer
extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws
IOException, JsonProcessingException {
String text = jsonParser.getText();
if("0".equals(text)) return false;
return true;
}
}
三、Write注解
Jackson 还包含一组注解,这些注解可以影响 Jackson 将 Java 对象序列化(写入)到 JSON 的方式。
1. @JsonInclude
注解 @JsonInclude 告诉 Jackson 仅在某些情况下包括属性。 例如,仅当属性为非 null,非空或具有非默认值时,才应包括该属性。
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class PersonInclude {
public long personId = 0;
public String name = null;
}
如果直接创建一个 PersonInclude 类,并将其序列化,那么将得到:
{"id":0}
2. @JsonGetter
@JsonGetter 注解用于告诉 Jackson,应该通过调用 getter 方法而不是通过直接字段访问来获取某个字段值。
public class PersonGetter {
private long personId = 0;
@JsonGetter("id")
public long personId() { return this.personId; }
@JsonSetter("id")
public void personId(long personId) { this.personId = personId; }
}
该 JSON 对象中 personId 的名称是 id。 生成的 JSON 对象如下所示:
{"id":0}
3. @JsonAnyGetter
@JsonAnyGetter 注解可以将 Map 用作要序列化为 JSON 的属性的容器。 这是在 Java 类中使用 @JsonAnyGetter 注解的示例:
public class PersonAnyGetter {
private Map<String, Object> properties = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> properties() {
return properties;
}
}
Jackson 将从 @JsonAnyGetter 注解的方法中获取返回的 Map,并将该 Map 中的每个键值对都视为一个属性。 换句话说,Map 中的所有键值对都将作为 PersonAnyGetter 对象的一部分序列化为 JSON。
注意,这种情况下,也会把 properties 属性给序列化。
4. @JsonPropertyOrder
@JsonPropertyOrder 可用于指定将Java对象的字段序列化为JSON的顺序。
@JsonPropertyOrder({"name", "personId"})
public class PersonPropertyOrder {
public long personId = 0;
public String name = null;
}
通常,Jackson 会按照在类中找到的顺序序列化 PersonPropertyOrder 中的属性。 但是,@JsonPropertyOrder 注解指定了不同的顺序,在序列化的 JSON 输出中,name 属性将首先出现,personId 属性将随后出现。
5. @JsonRawValue
@JsonRawValue 注解告诉 Jackson 该属性值应直接写入 JSON 输出。 如果该属性是字符串,Jackson 通常会将值括在引号中,但是如果使用 @JsonRawValue 属性进行注解,Jackson 将不会这样做。
例如有以下对象需要序列化。
public class PersonRawValue {
public long personId = 0;
@JsonRawValue
public String address =
"{ /"street/" : /"Wall Street/", /"no/":1}";
}
如果不加 @JsonRawValue 注解,结果为:
{"personId":0,"address":"{ /"street/" : /"Wall Street/", /"no/":1}"}
如果加上注解,则结果为:
{"personId":0,"address":{ "street" : "Wall Street", "no":1}}
6. @JsonValue
@JsonValue告诉Jackson,Jackson不应该尝试序列化对象本身,而应在对象上调用将对象序列化为JSON字符串的方法。
请注意,Jackson 将在自定义序列化返回的 String 内转义任何引号,因此不能返回完整的 JSON 对象。 为此,应该改用 @JsonRawValue。
例如有以下 java 对象:
public class PersonValue {
public long personId = 0;
public String name = null;
@JsonValue
public String toJson(){
return this.personId + "," + this.name;
}
}
序列化后的结果为:
"0,null"
引号由 Jackson 添加。 请记住,对象返回的值字符串中的所有引号均会转义。
7. @JsonSerialize
@JsonSerialize 注解用于为Java对象中的字段指定自定义序列化程序。
public class PersonSerializer {
public long personId = 0;
public String name = "John";
@JsonSerialize(using = OptimizedBooleanSerializer.class)
public boolean enabled = false;
}
OptimizedBooleanSerializer 类如下:
public class OptimizedBooleanSerializer extends JsonSerializer<Boolean> {
@Override
public void serialize(Boolean aBoolean, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
if(aBoolean){
jsonGenerator.writeNumber(1);
} else {
jsonGenerator.writeNumber(0);
}
}
}