我是靠谱客的博主 爱撒娇御姐,最近开发中收集的这篇文章主要介绍Jackson注解使用分析Jackson常用注解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • Jackson常用注解
    • 1. 常用注解汇总
    • 2. 注解使用分析
      • @JsonInclude
      • @JsonAnyGetter
      • @JsonAnySetter
      • @JsonNaming
      • @JsonAutoDetect
      • @JacksonInject
      • @JsonAlias
      • @JsonValue
      • @JsonMerge
      • @JsonRawValue
      • @JsonEnumDefaultValue
      • @JsonFilter
      • @JsonSerialize
      • @JsonDeserialize
      • @JacksonAnnotation
      • @JacksonAnnotationsInside
      • @JsonAppend
      • @JsonIdentityInfo
      • @JsonIdentityReference
      • @JsonBackReference
      • @JsonManagedReference
      • @JsonPOJOBuilder
    • 3. 自定义Jackson组合注解


Jackson常用注解

1. 常用注解汇总

注解作用范围主要属性描述
JsonProperty字段、方法value:指定json字段名
access:指定权限
required:
index:
defaultValue:
指定序列化、反序列化字段Json字段名
JsonPropertyOrdervalue:字段顺序数组,未配字段排在后面指定序列化时字段排序
JsonIgnore字段、get与set方法value:默认为true,为false不忽略指定序列化、反序列化忽略字段
JsonIgnoreTypevalue:默认为true,为false不忽略指定序列化、反序列化忽略类型(当该类作为别的类的属性时,忽略该类的所有字段)
JsonIgnorePropertiesvalue: 数组,指定要忽略的字段
ignoreUnknown:默认false,忽略不知道字段
allowGetters: 默认false,允许从get方法获取值
allowSetters:默认false,允许set方法设置值
指定序列化、反序列化忽略字段集合
JsonGettergetter方法value:指定json字段名指定序列化时的Json字段名,用于get方法上,优先级高于@JsonProperty
JsonSettersetter方法value:指定json字段名指定反序列化时的Json字段名,用于set方法上,优先级高于@JsonProperty
JsonInclude类、字段、方法value:序列化规则指定序列化规则
JsonRootNamevalue:根节点名称指定序列化、反序列化的根节点名称
JsonFormat字段、方法、参数pattern:时间格式
timezone:时区
设置序列化时的时间格式化格式
JsonAnyGetter方法enabled:是否启用,默认true作用于方法上,可以灵活地把类型为Map的属性作为标准属性序列化到JSON字符串中。方法返回值必须是Map。序列化时将Map中的key/value对展开到当前类的同一级
JsonAnySetter方法、字段enabled:是否启用,默认true一般作用于方法上,方法的入参必须有key、value。反序列化时,Json中与类不匹配的属性将会调用指定JsonAnySetter注解的方法,传入属性和属性值
JsonNamingvalue:属性命名策略指定序列化、反序列化的属性命名策略。
JsonCreator构造方法mode:指定模式指定反序列化使用的构造方法,需和JsonProperty注解配合使用,如:
@JsonCreator
public User(@JsonProperty(“id”)String id) {…}
JsonAutoDetect指定字段、方法的可见性
JsonUnwrapped字段、方法、参数enabled:是否开启,默认true
prefix:属性名称前缀
suffix:属性名称后缀
将其属性上拉移一个层级展开
JacksonInject字段、方法、参数value:字段标识
userInput:Json属性值是否覆盖默认值,默认TRUE
指定反序列化时,Json字段值是否覆盖实体类属性默认值
JsonAlias字段、方法、参数value:别名集合反序列化时,指定能匹配实体类属性的多个Json字段名称
JsonValue字段、方法value:是否启用一个类只能用一个,当加上JsonValue注解时,序列化时只返回这一个字段的值,而不是这个类的所有属性键值对。
一个类最多只能有一个JsonValue注解,否则会抛出异常;但多个类中可同时有一个JsonValue注解,序列化正常
JsonMerge字段、方法、参数value:是否启用合并反序列化时,将Json集合字段的元素与实体类对应属性默认元素合并
JsonRawValue字段、方法value:是否启用序列化时,属性值原样输出,属性值不会含转义和加引号(也就是属性值会自动去转义和去多余的引号)
JsonEnumDefaultValue字段-反序列化时,当枚举字段遇到未知的枚举值,使用JsonEnumDefaultValue注解指定的默认枚举值
需要注意:该注解需要开启DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE才生效
JsonFilter类、字段、方法、参数value:指定过滤器ID序列化时,过滤掉不需要的属性
JsonSerialize类、字段、方法、参数using:非null时使用的序列化器
nullsUsing:null时使用的序列化器
序列化时,指定字段序列化使用的序列化器
JsonDeserialize类、字段、方法、参数using:非null时使用的序列化器
nullsUsing:null时使用的序列化器
反序列化时,指定字段反序列化使用的反序列化器
JacksonAnnotation注解类-Jackson注解的元注解,注解上使用JacksonAnnotation表示该注解时Jackson相关注解
JacksonAnnotationsInside注解类-Jackson注解的元注解,可以将其他注解封装成一个组合注解,通常用于Jackson自定义注解
JsonView
JsonAppendattrs:序列化时要包括的一组虚拟属性
props:序列化时要包括的一组通用虚拟属性
prepend:虚拟属性附加在常规属性前面还是右面,默认false(后面)
用于在序列化对象时向对象添加虚拟属性
JsonIdentityInfo类、字段、方法、参数property:对象标识的属性名
generator:对象标识的生成器
用于处理对象的循环引用(序列化、反序列化),在第一次遇到时序列化为完整的对象,之后再遇到同一个对象,都以对象的标识符代替。能解决一对一、一对多、多对多的循环引用
JsonIdentityReference类、字段、方法、参数alwaysAsId:是否总是序列化为对象标识可以强制序列化为对象标识,而不是将第一个实例序列化为完整的 POJO,第二次才序列化为对象标识。必须与@JsonIdentityInfo 一起使用
JsonBackReference字段、方法@JsonBackReference标注的属性在序列化(serialization,即将对象转换为json数据)时,会被忽略(即结果中的json数据不包含该属性的内容)。
在序列化时,@JsonBackReference的作用相当于@JsonIgnore
JsonManagedReference字段、方法如果有@JsonManagedReference,则会自动注入@JsonBackReference标注的属性
JsonPOJOBuilderbuildMethodName: 无参数方法的名称,用于在将JSON字段绑定到bean的属性之后实例化预期的bean。默认名称为“build”
withPrefix: 用于自动检测JSON和bean属性之间的匹配的名称前缀。默认前缀是 with
用于配置构建器类,以自定义JSON文档的反序列化,以便在命名约定与默认约定不同的情况下恢复POJO。

2. 注解使用分析

@JsonInclude

序列化规则:

  • JsonInclude.Include. ALWAYS:默认,全部序列化

  • JsonInclude.Include.NON_NULL:非null字段序列化

  • JsonInclude.Include.NON_EMPTY:非null、非空字符串、非空数组、非空引用Optional、非空引用AtomicReference的字段序列化

  • JsonInclude.Include.NON_DEFAULT:值有变动的字段序列化

    何为有变动的字段:

    • 默认值:调用实体的无参构造函数创建一个实例,调用属性对应的get方法,将其返回值作为属性的默认值
    • 值有变动:属性的值与默认值不相同时,视为值有变动
  • JsonInclude.Include.NON_ABSENT:

  • JsonInclude.Include.CUSTOM:

@JsonAnyGetter

@JsonAnyGetter注解 可以灵活地把类型为Map的属性作为标准属性序列化到JSON字符串中,有如下特点:

  • 方法为非静态方法,并且方法不带任何参数,方法名没有特殊约定(随意定义方法名称)
  • 方法返回值必须是Map类型
  • 在一个实体类中只能用在一个方法上
public class User {
    private String id;
    private String userName;
    private String passWord;

    private Map<String, String> other;

    @JsonAnyGetter
    public Map<String, String> findOther() {
        return other;
    }

    public void addOther( String key,  String value) {
        if (other == null) {
            other = new HashMap<>();
        }
        other.put(key, value);
    }

    public String getId() {
        return id;
    }

    public User setId(String id) {
        this.id = id;
        return this;
    }

    public String getUserName() {
        return userName;
    }

    public User setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getPassWord() {
        return passWord;
    }

    public User setPassWord(String passWord) {
        this.passWord = passWord;
        return this;
    }
}
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.addOther("email", "1111@qq.com");
        user.addOther("email1", "2222@qq.com");
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email1" : "2222@qq.com",
  "email" : "1111@qq.com"
}

@JsonAnySetter

public class User {
    private String id;
    private String userName;
    private String passWord;

    private Map<String, String> other;

    public Map<String, String> findOther() {
        return other;
    }

    @JsonAnySetter
    public void addOther( String key,  String value) {
        if (other == null) {
            other = new HashMap<>();
        }
        other.put(key, value);
    }

    public String getId() {
        return id;
    }

    public User setId(String id) {
        this.id = id;
        return this;
    }

    public String getUserName() {
        return userName;
    }

    public User setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getPassWord() {
        return passWord;
    }

    public User setPassWord(String passWord) {
        this.passWord = passWord;
        return this;
    }
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":"111111@qq.com","nickName":null,"sex":"女","createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

user对象
在这里插入图片描述

@JsonNaming

PropertyNamingStrategy:属性命名策略,具体策略有:

策略名称描述举例
PropertyNamingStrategy小驼峰(默认策略)userName
SnakeCaseStrategy小写+下划线user_name
UpperCamelCaseStrategy大驼峰UserName
LowerCaseStrategy小写username
KebabCaseStrategy小写+连字符user-name
LowerDotCaseStrategy小写+点号user.name

匹配的优先级:JsonProperty注解指定的字段名称优先级高于JsonNaming注解指定的属性命名策略对应的字段名称

@JsonAutoDetect

默认情况下,Jackson 只使用 public 的字段进行序列化和反序列化。没有 public 字段时,会使用 public 的 getters/setters。通过@JsonAutoDetect可以指定字段、方法的可见性规则。

注解的属性:

  • getterVisibility:get方法的可见性,默认JsonAutoDetect.Visibility.DEFAULT
  • isGetterVisibility:is方法的可见性,默认JsonAutoDetect.Visibility.DEFAULT
  • setterVisibility:set方法的可见性,默认JsonAutoDetect.Visibility.DEFAULT
  • creatorVisibility:构造方法(非无参构造方法)的可见性,默认JsonAutoDetect.Visibility.DEFAULT
  • fieldVisibility:字段的可见性,默认JsonAutoDetect.Visibility.DEFAULT

JsonAutoDetect.Visibility:可见性枚举类

  • ANY:都可见
  • NON_PRIVATE:除private修饰的,其它都可见
  • PROTECTED_AND_PUBLIC:protected和public修饰的可见,其它不可见
  • PUBLIC_ONLY:只有public修饰的可见,其它都不可见
  • NONE:都不可见
  • DEFAULT:

java可见性修饰符:public、protected、默认、private

@JacksonInject

useInput属性,值为OptBoolean枚举类型

  • OptBoolean.TRUE:属性值覆盖默认值。
  • OptBoolean.FALSE:属性值不覆盖默认值,相当于定死了这个字段的值为默认值。
  • OptBoolean.DEFAULT:默认值,等同于OptBoolean.TRUE。该值主要是为了向后兼容(2.8 和更早版本始终允许绑定输入值)。
@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JacksonInject(value = "nickName")
    private String nickName;
    private Date createTime;
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":null,"createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue("nickName","小明");
        objectMapper.setInjectableValues(injectableValues);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    // 输出:User(id=999, userName=小五, passWord=888888, email=null, nickName=小明, createTime=null)
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue("nickName","小明");
        objectMapper.setInjectableValues(injectableValues);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    // 输出:User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null)

@JsonAlias

@Data
public class User {
    private String id;
    @JsonAlias({"userName1", "userName2" })
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    // 输出:User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null)
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName1":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    // 输出:User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null)
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName2":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    // 输出:User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null)

@JsonValue

JsonValue注解一般用在属性字段或者get方法上。当加上@JsonValue注解时,序列化时只返回这一个字段的值,而不是这个类的所有属性键值对。
需要注意:

  • 一个类最多只能有一个JsonValue注解,否则会抛出异常
  • 多个类中可同时有一个JsonValue注解,序列化正常
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setCardInfo(new CardInfo("1", "123445"));
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

例1:

@Data
public class User {
    private String id;
    private String userName;
    @JsonValue
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CardInfo {

    private String cardType;
    private String cardNum;
}

输出

"888888"

例2:

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CardInfo {

    @JsonValue
    private String cardType;
    private String cardNum;
}

输出

{"id":"999","userName":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null,"cardInfo":"1"}

例3:

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CardInfo {

    @JsonValue
    private String cardType;
    @JsonValue
    private String cardNum;
}

输出

com.fasterxml.jackson.databind.JsonMappingException: Problem with definition of [AnnotedClass com.joker.test.json.CardInfo]: Multiple 'as-value' properties defined ([field com.joker.test.json.CardInfo#cardType] vs [field com.joker.test.json.CardInfo#cardNum]) (through reference chain: com.joker.test.json.User["cardInfo"])
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:292)
	at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1223)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1341)
	at com.fasterxml.jackson.databind.SerializerProvider.findPrimaryPropertySerializer(SerializerProvider.java:668)
	at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddPrimarySerializer(PropertySerializerMap.java:64)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._findAndAddDynamic(BeanPropertyWriter.java:897)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:705)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
	at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4094)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3404)
	at com.joker.test.json.JacksonTest.object2JsonStr(JacksonTest.java:152)
	at com.joker.test.json.JacksonTest.main(JacksonTest.java:267)

一个类出现多个JsonValue注解,序列化会抛出异常。

例4:

@Data
public class User {

    private String id;
    private String userName;
    @JsonValue
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CardInfo {

    @JsonValue
    private String cardType;
    private String cardNum;
}

输出

"888888"

多个类中同时有一个JsonValue注解,序列化正常。

@JsonMerge

反序列化时,将Json集合字段的元素与实体类对应属性默认元素合并。

@Data
public class User {

    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
    @JsonMerge
    private List<String> list = new ArrayList<>(Collections.singletonList("篮球"));
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null,"cardInfo":{"cardType":"1","cardNum":"123445"},"list":["排球","足球","乒乓球"]}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

输出

User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null, cardInfo=CardInfo(cardType=1, cardNum=123445), list=[篮球, 排球, 足球, 乒乓球])

list集合将默认元素"篮球"和Json串中list字段的元素"排球","足球","乒乓球"进行了合并。

@JsonRawValue

序列化时,属性值原样输出,属性值不会含转义和加引号(也就是属性值会自动去转义和去多余的引号)

@Data
public class User {

    private String id;
    private String userName;
    private String passWord;
    @JsonRawValue
    private String email;
    private String nickName;
    private Date createTime;
}
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com\");
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : 111111@qq.com,
  "nickName" : null,
  "createTime" : null,
  "cardInfo" : {
    "cardType" : "1",
    "cardNum" : "123445"
  }
}

@JsonEnumDefaultValue

@Data
public class User {

    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private SexEnum sex;
}
enum SexEnum {
    @JsonEnumDefaultValue
    MAN,
    WOMAN
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":null,"nickName":null,"createTime":null,"sex":"男"}";
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

输出

User(id=999, userName=小五, passWord=888888, email=null, nickName=null, createTime=null, sex=MAN)

@JsonFilter

JsonFilter 注解的作用是通过属性名过滤要序列化的属性。

它指定一个过滤器的ID,通过ObjectMapper注册真正的过滤器,过滤器需要实现接口 com.fasterxml.jackson.databind.ser.PropertyFilter。一般使用SimpleBeanPropertyFilter过滤器。

SimpleBeanPropertyFilterde的主要方法:

  • serializeAllExcept:过滤掉指定字段,保留其它字段
  • filterOutAllExcept:保留指定的字段,过滤掉其它字段

1. 用于类上

@Data
@JsonFilter("userFilter")
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private CardInfo cardInfo;
}
    private static void objectFiilter2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCardInfo(new CardInfo("1", "500210190001017771"));

        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        // filterProvider.addFilter("userFilter",SimpleBeanPropertyFilter.filterOutAllExcept("passWord"));// 保留指定的字段,过滤掉其它字段
        filterProvider.addFilter("userFilter",SimpleBeanPropertyFilter.serializeAllExcept ("passWord"));// 过滤掉指定字段,保留其它字段

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        objectMapper.setFilterProvider(filterProvider);

        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出:

{
  "id" : "999",
  "userName" : "小五",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : null,
  "cardInfo" : {
    "cardType" : "1",
    "cardNum" : "500210190001017771"
  }
}

过滤掉了
2. 用于字段上

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    @JsonFilter("userFilter")
    private CardInfo cardInfo;
}

@Data
class CardInfo {

    // @JsonValue
    private String cardType;
    private String cardNum;

    public CardInfo() {
    }

    public CardInfo(String cardType, String cardNum) {
        this.cardType = cardType;
        this.cardNum = cardNum;
    }
}
    private static void objectFiilter2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCardInfo(new CardInfo("1", "500210190001017771"));

        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        filterProvider.addFilter("userFilter",SimpleBeanPropertyFilter.serializeAllExcept ("cardNum"));// 过滤掉指定字段,保留其它字段

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        objectMapper.setFilterProvider(filterProvider);

        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出:

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : null,
  "cardInfo" : {
    "cardType" : "1"
  }
}

@JsonSerialize

序列化时,指定字段序列化使用的序列化器。

JsonSerialize注解的部分属性:

  • using:指定非null值时使用的序列化器
  • nullsUsing:指定null值时使用的序列化器

若要自定义序列化器,一般通过继承StdSerializer或者JsonSerializer实现。

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JsonSerialize(using = SexEnumSerializer.class)
    private SexEnum sex;
    private String nickName;
    private Date createTime;
}

enum SexEnum {
    MAN("男"),
    WOMAN("女");

    private String value;

    SexEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public SexEnum setValue(String value) {
        this.value = value;
        return this;
    }

    public static SexEnum getByValue(String value) {
        for (SexEnum sexEnum : SexEnum.values()) {
            if (sexEnum.getValue().equals(value)) {
                return sexEnum;
            }
        }
        return null;
    }
}
// 方式1:继承StdSerializer
public class SexEnumSerializer extends StdSerializer<SexEnum> {

    public SexEnumSerializer() {
        this(null);
    }

    public SexEnumSerializer(Class<SexEnum> t) {
        super(t);
    }

    @Override
    public void serialize(SexEnum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.getValue());
    }
}

// 方式2:继承JsonSerializer
public class SexEnumSerializer extends JsonSerializer<SexEnum> {

    @Override
    public void serialize(SexEnum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.getValue());
    }
}
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setSex(SexEnum.MAN);
        user.setCreateTime(new Date());
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "sex" : "男",
  "nickName" : null,
  "createTime" : 1673157947671
}

@JsonDeserialize

反序列化时,指定字段反序列化使用的反序列化器。

JsonDeserialize注解的部分属性:

  • using:指定非null值时使用的反序列化器
  • nullsUsing:指定null值时使用的反序列化器

若要自定义反序列化器,一般通过继承StdDeserializer或者JsonDeserializer实现。

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JsonDeserialize(using = SexEnumDeserializer.class)
    private SexEnum sex;
    private String nickName;
    private Date createTime;
}

enum SexEnum {
    @JsonEnumDefaultValue
    MAN("男"),
    WOMAN("女");

    private String value;

    SexEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public SexEnum setValue(String value) {
        this.value = value;
        return this;
    }

    public static SexEnum getByValue(String value) {
        for (SexEnum sexEnum : SexEnum.values()) {
            if (sexEnum.getValue().equals(value)) {
                return sexEnum;
            }
        }
        return null;
    }
}
// 方式1:继承StdDeserializer
public class SexEnumDeserializer extends StdDeserializer<SexEnum> {

    public SexEnumDeserializer() {
        this(null);
    }

    public SexEnumDeserializer(Class<String> t) {
        super(t);
    }

    @Override
    public SexEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = p.getText();
        return SexEnum.getByValue(value);
    }
}

// 方式2:继承StdDeserializer
public class SexEnumDeserializer extends JsonDeserializer<SexEnum> {

    @Override
    public SexEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = p.getText();
        return SexEnum.getByValue(value);
    }
}
    private static void jsonStr2Object() {
        String jsonStr = "{"id":"999","userName":"小五","passWord":"888888","email":"111111@qq.com","nickName":null,"sex":"女","createTime":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

输出

User(id=999, userName=小五, passWord=888888, email=111111@qq.com, sex=WOMAN, nickName=null, createTime=null)

@JacksonAnnotation

注解上使用JacksonAnnotation表示该注解时Jackson相关注解。

所有的Jsonson注解类上都有JacksonAnnotation元注解。

@JacksonAnnotationsInside

Jackson注解的元注解,可以将其他注解封装成一个组合注解,通常用于Jackson自定义组合注解。

@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JsonSerialize(using = SexEnumSerializer.class)
    @JsonDeserialize(using = SexEnumDeserializer.class)
    private SexEnum sex;
    private String nickName;
    private Date createTime;
}

enum SexEnum {
    MAN("男"),
    WOMAN("女");

    private String value;

    SexEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public SexEnum setValue(String value) {
        this.value = value;
        return this;
    }

    public static SexEnum getByValue(String value) {
        for (SexEnum sexEnum : SexEnum.values()) {
            if (sexEnum.getValue().equals(value)) {
                return sexEnum;
            }
        }
        return null;
    }
}

通过@JacksonAnnotationsInside自定义注解可改为

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JsonSerialize(using = SexEnumSerializer.class)
@JsonDeserialize(using = SexEnumDeserializer.class)
@JacksonAnnotationsInside
public @interface JsonSexSerializeDeserialize {

}
@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JsonSexSerializeDeserialize
    private SexEnum sex;
    private String nickName;
    private Date createTime;
}

enum SexEnum {
    MAN("男"),
    WOMAN("女");

    private String value;

    SexEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public SexEnum setValue(String value) {
        this.value = value;
        return this;
    }

    public static SexEnum getByValue(String value) {
        for (SexEnum sexEnum : SexEnum.values()) {
            if (sexEnum.getValue().equals(value)) {
                return sexEnum;
            }
        }
        return null;
    }
}

@JsonAppend

@JsonAppend注解用于在序列化对象时向对象添加虚拟属性。

当我们希望直接向序列化后JSON字符串中添加补充信息而不是更改类定义时,可以使用@JsonAppend。
注解的主要属性:

  • attrs:序列化时要包括的一组虚拟属性
  • props:序列化时要包括的一组通用虚拟属性
  • prepend:虚拟属性附加在常规属性前面还是右面,默认false(后面)

例1:使用attrs属性

@Data
@JsonAppend(attrs = {@JsonAppend.Attr(value = "age"),@JsonAppend.Attr(value = "sex")})
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
}
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writerFor(User.class).withAttribute("age", "20").withAttribute("sex", "男").writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : 1675151635581,
  "age" : "20",
  "sex" : "男"
}

例2:使用props属性

@Data
@JsonAppend(props = {@JsonAppend.Prop(value =TestWriter.class ,type = String.class,name = "idcard")}, prepend = true)
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
}

@NoArgsConstructor
class TestWriter extends VirtualBeanPropertyWriter {


    private TestWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) {
        super(propDef, contextAnnotations, declaredType);
    }


    @Override
    protected Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
        return "5002001564564565";
    }

    @Override
    public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) {
        return new TestWriter(propDef, declaringClass.getAnnotations(), type);
    }
}
    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "idcard" : "5002001564564565",
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : 1675151702894
}

@JsonIdentityInfo

@JsonIdentityInfo用于处理对象的循环引用,方法是只在第一次遇到时序列化为完整的对象,之后再遇到同一个对象,都以对象的标识符代替。

生成对象标识符有两种方法:

  • 使用生成器(标准生成器或自定义生成器之一)
  • 直接使用属性的值(通过使用占位符生成器标记ObjectIdGenerators.PropertyGenerator)

对象标识目前不支持JSON数组类型(Java数组或列表)或Java Map类型。

注解的主要属性:

  • property:对象标识的属性名
  • generator:对象标识的生成器
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private User user;
}

1. 循环引用

    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        user.setUser(user);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : 1675156428169,
  "user" : "999"
}

2. 非循环引用

    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        User user1 = new User();
        user1.setId("888");
        user1.setUserName("小六");
        user.setUser(user1);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

{
  "id" : "999",
  "userName" : "小五",
  "passWord" : "888888",
  "email" : "111111@qq.com",
  "nickName" : null,
  "createTime" : 1675156549005,
  "user" : {
    "id" : "888",
    "userName" : "小六",
    "passWord" : null,
    "email" : null,
    "nickName" : null,
    "createTime" : null,
    "user" : null
  }
}

@JsonIdentityReference

@JsonIdentityReference 必须与 @JsonIdentityInfo 一起使用。

@JsonIdentityInfo在第二次遇到时才序列化为对象标识,@JsonIdentityReference可以强制序列化为对象标识,而不是将第一个实例序列化为完整的POJO。

注解的主要属性:

  • alwaysAsId:是否总是序列化为对象标识,默认false。当为true时,在第一次时就会序列化为对象标识,而不是等到第二次cai序列化为对象标识(@JsonIdentityInfo的规则)

注意事项:

  • 使用@JsonIdentityInfo标识遇到循环引用时,将第一个实例序列化为完整的POJO,第二次才序列化为对象标识。
  • 如果加上了@JsonIdentityReference,表示第一次就直接序列化为对象标识(无论是否是循环引用)
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = true)
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;
    private User user;
}

1. 循环引用

    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        user.setUser(user);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

"999"

2. 非循环引用

    private static void object2JsonStr() {
        User user = new User();
        user.setId("999");
        user.setUserName("小五");
        user.setPassWord("888888");
        user.setEmail("111111@qq.com");
        user.setCreateTime(new Date());
        User user1 = new User();
        user1.setId("888");
        user1.setUserName("小六");
        user.setUser(user1);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String jsonStr = objectMapper.writeValueAsString(user);
            System.out.println(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出

"999"

@JsonBackReference

与下面@JsonManagedReference一起分析

@JsonManagedReference

Jackson中的@JsonBackReference和@JsonManagedReference,以及@JsonIgnore均是为了解决对象中存在双向引用导致的无限递归问题。这些标注均可用在属性或对应的get、set方法中。

@JsonBackReference和@JsonManagedReference两个标注通常配对使用,通常用在父子关系中。

@JsonIgnore、@JsonBackReference、@JsonManagedReference对比:

  • @JsonIgnore:直接忽略某个属性,以断开无限递归,序列化或反序列化均忽略。

    当然如果标注在get、set方法中,则可以分开控制,序列化对应的是get方法,反序列化对应的是set方法。

    在父子关系中,当反序列化时,@JsonIgnore不会自动注入被忽略的属性值(父或子),这是它跟@JsonBackReference和@JsonManagedReference最大的区别。

  • @JsonBackReference:@JsonBackReference标注的属性在序列化时,会被忽略。

    在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。

    但在反序列化(deserialization,即json数据转换为对象)时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子)

  • @JsonManagedReference:用于在反序列化时,自动注入@JsonBackReference标注的属性

public class Test {
    public static void main(String[] args) throws IOException {

        Order order = new Order();
        Customer customer = new Customer();

        customer.setId(2);
        customer.setName("Peter");
        customer.setOrder(order);

        order.setOrderId(1);
        order.setItemIds(Stream.of(10, 30).collect(Collectors.toList()));
        order.setCustomer(customer);

        ObjectMapper om = new ObjectMapper();
        String serializing = om.writeValueAsString(customer);

        Customer deserializing = om.readValue(serializing, Customer.class);
    }
}

@Data
class Customer {
    private int id;
    private String name;
    @JsonManagedReference
    private Order order;
}

@Data
class Order {
    private int orderId;
    private List<Integer> itemIds;
    @JsonBackReference
    private Customer customer;
}

调试过程:
在这里插入图片描述
可见:

  • 序列化时,忽略了order中的customer属性
  • 反序列化时,又自动注入了order中的customer属性

@JsonPOJOBuilder

@JsonPOJOBuilder注解用于配置构建器类,以自定义JSON文档的反序列化,以便在命名约定与默认约定不同的情况下恢复POJO。

@JsonPOJOBuilder主要用与bean的属性名称与JSON字符串中的字段名称不同的场景。

注解的主要属性:

  • buildMethodName: 无参数方法的名称,用于在将JSON字段绑定到bean的属性之后实例化预期的bean。默认名称为“build”。
  • withPrefix: 用于自动检测JSON和bean属性之间的匹配的名称前缀。默认前缀是 with。
@Data
@JsonDeserialize(builder = UserBuilder.class)
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    private String nickName;
    private Date createTime;

    public User() {
    }

    public User(String id, String userName) {
        this.id = id;
        this.userName = userName;
    }
}

@JsonPOJOBuilder(buildMethodName = "createBean", withPrefix = "construct")
class UserBuilder {
    private String userId;
    private String name;

    public UserBuilder constructUserId(String userId) {
        this.userId = userId;
        return this;
    }

    public UserBuilder constructName(String name) {
        this.name = name;
        return this;
    }

    public User createBean() {
        return new User(userId, name);
    }
}
    private static void jsonStr2Object() {
        String jsonStr = "{"userId":"999","name":"小五"}";
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
        try {
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

输出

User(id=999, userName=小五, passWord=null, email=null, nickName=null, createTime=null)

3. 自定义Jackson组合注解

Jackson通过JacksonAnnotationsInside注解来自定义Jackson组合注解。

例如:自定义Jackson组合注解:JsonSexSerializeDeserialize。

该注解的作用:

  • 序列化时,将枚举对象SexEnum转化为字符串值"男"或"女"
  • 反序列化时,将字符串值"男"或"女"转化为枚举对象SexEnum
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JsonSerialize(using = SexEnumSerializer.class)
@JsonDeserialize(using = SexEnumDeserializer.class)
@JacksonAnnotationsInside
public @interface JsonSexSerializeDeserialize {

}
public class SexEnumSerializer extends JsonSerializer<SexEnum> {

    @Override
    public void serialize(SexEnum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.getValue());
    }
}
public class SexEnumDeserializer extends JsonDeserializer<SexEnum> {

    @Override
    public SexEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = p.getText();
        return SexEnum.getByValue(value);
    }
}
@Data
public class User {
    private String id;
    private String userName;
    private String passWord;
    private String email;
    @JsonSexSerializeDeserialize
    private SexEnum sex;
    private String nickName;
    private Date createTime;
}

enum SexEnum {
    MAN("男"),
    WOMAN("女");

    private String value;

    SexEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public SexEnum setValue(String value) {
        this.value = value;
        return this;
    }

    public static SexEnum getByValue(String value) {
        for (SexEnum sexEnum : SexEnum.values()) {
            if (sexEnum.getValue().equals(value)) {
                return sexEnum;
            }
        }
        return null;
    }
}

最后

以上就是爱撒娇御姐为你收集整理的Jackson注解使用分析Jackson常用注解的全部内容,希望文章能够帮你解决Jackson注解使用分析Jackson常用注解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部