Jackson 常用注解

316次阅读
没有评论

共计 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);
        }
    }
}

提醒:本文发布于174天前,文中所关联的信息可能已发生改变,请知悉!

AD:【腾讯云服务器大降价】2核4G 222元/3年 1核2G 38元/年
正文完
 
阿蛮君
版权声明:本站原创文章,由 阿蛮君 2023-09-03发表,共计6233字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
Copyright © 2022-2024 阿蛮君博客 湘ICP备2023001393号
本网站由 亿信互联 提供云计算服务 | 蓝易云CDN 提供安全防护和加速服务