JackSon 注解笔记

超全的JackSon注解大全包含demo https://www.tutorialspoint.com/jackson_annotations/index.htm

  • @JsonProperty 属性注解 可以修改序列化别名、默认值、展示效果
  • @JsonView 属性和方法注解 可以在不同视图中显示不同的序列化
  • @JsonCreator 方法注解 控制序列化使用的构造函数
  • @JsonValue 属性注解 控制某属性作为序列化的唯一结果输出
  • @JsonUnwrapped 对象扁平化把子属性对象解构提取到根对象
  • @JsonTypeName 配合@JsonTypeInfo指定序列化时属性对应名称
  • @JsonTypeInfo 解决多态反序列化问题 这里的大佬总结的很好
  • @JsonSubTypes 解决多态序列化时,无法确认子类类型的问题
  • @JsonTypeIdResolver 多态序列化相关 这部分可以看这个大佬的总结
  • @JsonTypeId 指定序列化时的key值
  • @JsonRawValue 是否按照字面量序列化,就是序列化结果是字符”key”:”xxx”还是”key”:xxx
  • @JsonManagedReference, @JsonBackReference 解决循环引用 具体的案例看这里
  • @JsonInclude 可以实现根据条件过滤key或value值 比如隐藏所有null值不序列化
  • @JsonIgnoreType 标记在类上,所有以该类为类型的值都会被忽略
  • @JsonIgnoreProperties 标记在类上,控制该类哪些属性被隐藏,还可以控制遇到json字符串未知参数是否抛出异常 ignoreUnknown
  • @JsonIdentityReference @JsonIdentityInfo 解决循环引用问题 具体demo看这里 @JsonIdentityReference可以让第二次序列化的对象(存在循环引用的对象)序列化为它的id值,@JsonIdentityReference 设alwaysAsId=true会让对象直接序列化为它的id值
  • @JsonGetter 指定序列化时使用的方法,可用于定义非静态、无参数返回值(非 void)方法,用作逻辑属性的“getter”。它可以用作更通用 JsonProperty注释的替代方法(这是一般情况下的推荐选择)。Getter 是指在序列化具有该方法的类的 Object 实例时(可能继承自超类),通过该方法进行调用,并将返回值序列化为该属性的值。
  • @JsonFormat 序列化时指定格式,常用于各种时间格式
  • @JsonFilter 定义一个过滤器的名称 在序列化时根据该名称指定序列化器 具体demo看这里
  • @JsonAnySetter 该注解允许我们把一个可变的map属性作为标准属性, 在反序列过程中, 从Json字符串得到的属性值会加入到map属性中,可以用它来存不存在于类中的属性。
  • @JsonAnyGetter 该注解用于把可变的Map类型属性当做标准属性,和@JsonAnySetter一起使用
  • @JacksonInject 指定属性是注入的而不是从Json字符串中反序列化获取
  • @JsonAutoDetect 可以覆盖可见性,可以指定属性的可见性
  • @JacksonAnnotation,@JacksonAnnotationsInside 属于JackSon的元注解

@JsonProperty

注意:虽然官方文档说 该注解如果和@JsonIgnore一同使用,@JsonIgnore 则优先于此属性。但实际测试用发现如果两个注解同时存在,效果等同 READ_ONLY,序列化都能展示,反序化不能写入。


String value: 指定序列化key
String defaultValue: 指定key的默认值
boolean	required:是否必须,但请注意,从 2.6 开始,此属性仅用于 Creator 属性,以确保 JSON 中存在属性值:对于其他属性(使用 setter 或可变字段注入的属性),不执行验证,也就是说只和@JsonCreator一起使用时生效。
int index: 指定该字段排序
JsonProperty.Access access: 序列化权限控制 有下列四种

  • AUTO 自动确定此属性的读取和/或写入访问权限。
  • READ_ONLY 只能在序列化时读取,而在反序列化期间不能写入(设置)。
  • READ_WRITE 无论可见性规则如何,都将访问该属性以进行序列化(将值写为外部表示)和反序列化(从外部表示中读取值)。
  • WRITE_ONLY 只能被写(set)用于反序列化,而不会被读(get)在序列化时,即该属性的值不包含在序列化中。

序列化权限控制测试代码:MyTest.java

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class MyTest {

    @JsonProperty(access = AUTO)
    public String myA;

    @JsonProperty(access = READ_ONLY)
    public String myB;

    @JsonProperty(access = WRITE_ONLY)
    public String myC;

    @JsonProperty(access = READ_WRITE)
    public String myD;

    public static void main(String[] args) throws JsonProcessingException {
        MyTest myTest = MyTest.builder().myA("A").myB("B").myC("C").myD("D").build();
        ObjectMapper mapper = new ObjectMapper();
        String toJson = mapper.writeValueAsString(myTest);
        System.out.println("=======预期打印======");
        System.out.println("{\"myA\":\"A\",\"myB\":\"B\",\"myC\":\"C\",\"myD\":\"D\"}");
        System.out.println("=======序列化打印=====");
        System.out.println(toJson);
        System.out.println("=======反列化打印=====");
        String fromJson = "{\"myA\":\"A\",\"myB\":\"B\",\"myC\":\"C\",\"myD\":\"D\"}";
        MyTest test = mapper.readValue(fromJson,MyTest.class);
        System.out.println(test);
    }
}
输出结果:
=======预期打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
MyTest(myA=A, myB=B, myC=C, myD=D)
=======序列化打印=====
{"myA":"A","myB":"B","myD":"D"}
=======反列化打印=====
MyTest(myA=A, myB=null, myC=C, myD=D)

@JsonCreator

JackSon默认使用无参构造方法和set方法反序列对象,使用该注解可以指定JaskSon使用指定方法进行反序列化构造对象,可以标注在构造方法和静态工厂方法上。

@JsonView

@JsonView使用方法:

  1.使用接口来声明多个视图 例如下面这个 代码来自baeldung.com

public class Views {
    public static class Public {
    }

    public static class Internal extends Public {
    }
}
public class Item {
 
    @JsonView(Views.Public.class)
    public int id;

    @JsonView(Views.Public.class)
    public String itemName;

    @JsonView(Views.Internal.class)
    public String ownerName;
}

  2.在pojo的属性上指定视图

public class Item {
 
    @JsonView(Views.Public.class)
    public int id;

    @JsonView(Views.Public.class)
    public String itemName;

    @JsonView(Views.Internal.class)
    public String ownerName;
}

  3.在Controller方法上指定视图

@JsonView(Views.Internal.class)
@RequestMapping("/items/internal/{id}")
public Item getItemInternal(@PathVariable int id) {
    return ItemManager.getById(id);
}

4.直接进行序列化或反序列化时可以指定视图

@Test
public void whenUseJsonViewToDeserialize_thenCorrect() 
  throws IOException {
    String json = "{"id":1,"name":"John"}";

    ObjectMapper mapper = new ObjectMapper();
    User user = mapper
      .readerWithView(Views.Public.class)
      .forType(User.class)
      .readValue(json);

    assertEquals(1, user.getId());
    assertEquals("John", user.getName());
}

@JsonValue

@JsonView是jackson json中的一个注解,指定属性后序列化将只使用该属性值作为序列化接口(这个注解只能作用于一个属性上)。

@JsonUnwrapped

@JsonUnwrapped 对象扁平化 如果属性序列化后是一个对象 会将该属性的对象解构提取到根对象中。

@JsonTypeName

用于绑定被注释类所具有的逻辑名称的注释。与JsonTypeInfo(特别是JsonTypeInfo.use()属性)一起使用以建立对象名称和属性之间的关系,反序列化为父类时,用于确定该对象的具体类型,与@JsonSubTypes 直接标注在父类等效。

@JsonTypeInfo

用于多态类型处理

Class<?> defaultImpl 指定默认的反序列化类型,当反序列对象无法映射到现在有的指定类型时会使用它进行反序列化。

JsonTypeInfo.As include 指定类型标识信息的展示方式。
有下列5种可选值 下面的测试结果使用的注解是@JsonTypeInfo(use= JsonTypeInfo.Id.NAME)

PROPERTY 使用单个可配置属性的包含机制,与实际数据(POJO 属性)一起作为单独的元属性包含在内。,这个属性的值由 @JsonTypeInfo注解的property确定,否则就使用不同use情况下的默认值(@class、@c、@type)。

@JsonTypeInfo(use= JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY )
结果:
=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
{"@type":"MyTest","myA":"A","myB":"B","myC":"C","myD":"D"}

EXISTING_PROPERTY 与PROPERTY区别在于,该注解在序列化时不会输出标识符,反序列流程根PROPERTY相同。

EXTERNAL_PROPERTY 只作用于属性上,把子属性的标识符提升到根对象里,具体使用场景没搞明白。

WRAPPER_OBJECT 包裹在一个对象中,相当于在外层创建一个父对象 {标识符:{原本的对象}} 用一个大对象包住

@JsonTypeInfo(use= JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.EXTERNAL_PROPERTY )
结果:
=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
{"MyTest":{"myA":"A","myB":"B","myC":"C","myD":"D"}}

WRAPPER_ARRAY 包裹在一个数组中。

@JsonTypeInfo(use= JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.WRAPPER_ARRAY )
结果:
=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
["MyTest",{"myA":"A","myB":"B","myC":"C","myD":"D"}]

JsonTypeInfo.Id use 指定在序列化时类型标识信息展示的值。
有下列5种可选值

CLASS 意味着使用完全限定的 Java 类名作为类型标识符。

测试结果:可以看到序列化对象多了一个 @class key,而且其值为全限定类名。(若不指定property则默认为@class

=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印========{"@class":"com.example.demo.bean.MyTest","myA":"A","myB":B,"myC":"C","myD":"D"}

CUSTOM 意味着键入机制使用自定义处理,可能具有自定义配置。这个注解需结合property属性和@JsonTypeIdResolver一起使用,指定类标识符的值。

@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
@JsonTypeIdResolver(JacksonTypeIdResolver.class)
实现TypeIdResolver接口 自定义序列化流程

MINIMAL_CLASS 表示使用具有最小路径的 Java 类名作为类型标识符,多了一个”@c“字段,其值为最小路径类名。(若不指定property则默认为@c

=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
{"@c":".MyTest","myA":"A","myB":"B","myC":"C","myD":"D"}

NAME 表示使用逻辑类型名作为类型信息;然后需要将名称单独解析为实际的具体类型(类),多了一个”@type”字段,其值为类名。(若不指定property则默认为@type

=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
{"@type":"MyTest","myA":"A","myB":"B","myC":"C","myD":"D"}

NONE 这意味着不包含显式类型元数据,并且键入纯粹是使用上下文信息完成的,可能会增加其他注释。

=======未配置注解打印======
{"myA":"A","myB":"B","myC":"C","myD":"D"}
=======配置注解打印=======
{"myA":"A","myB":"B","myC":"C","myD":"D"}

String property 指定类标识名称,在include=JsonTypeInfo.As.PROPERTY或use=JsonTypeInfo.Id.CUSTOM生效,其他情况使用默认的识别码名称。
注意:include=JsonTypeInfo.As.PROPERTY和property同时存在有个问题,如果POJO具有相同名称的属性,会出现两个!

@JsonSubTypes

用来列出给定类的子类,只有当子类类型无法被检测到时才会使用它,也可以在子类上直接使用@JsonTypeName 实现同等效果。

《JackSon 注解笔记》上有2条评论

  1. Hello there! I could have sworn I’ve been to this site before but after checking through some of the post I realized it’s new to me.
    Anyways, I’m definitely glad I found it and I’ll
    be bookmarking and checking back often!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注