本文来说下Jackson中的注解。

文章目录

  • 概述
  • Read + Write注解
    • @JsonIgnore
    • @JsonIgnoreProperties
    • @JsonIgnoreType
    • @JsonAutoDetect
  • Read注解
    • @JsonSetter
    • @JsonAnySetter
    • @JsonCreator
    • @JacksonInject
    • @JsonDeserialize
  • Write注解
    • @JsonInclude
    • @JsonGetter
    • @JsonAnyGetter
    • @JsonPropertyOrder
    • @JsonRawValue
    • @JsonValue
    • @JsonSerialize
  • 本文小结

概述

本文来说下序列化框架Jackson的详细使用。Spring MVC默认采用Jackson解析Json,尽管还有一些其它同样优秀的json解析工具,例如Fast Json、GSON,但是出于最小依赖的考虑,也许Json解析第一选择就应该是Jackson。Jackson JSON工具包包含一组Java注解,可以使用这些注解来设置将JSON读入对象的方式或从对象生成什么JSON的方式。 此Jackson注解教程介绍了如何使用Jackson的注解。

下面是一些常用的注解

注解 用法
@JsonProperty 用于属性,把属性的名称序列化时转换为另外一个名称。示例:@JsonProperty(“birth_ d ate”)private Date birthDate;
@JsonFormat 用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例: @JsonFormat(timezone = “GMT+8”, pattern = “yyyyMM-dd HH:mm”) public DategetBirthDate()
@JsonPropertyOrder 用于类, 指定属性在序列化时 json 中的顺序 , 示例:@JsonPropertyOrder({ “birth_Date”, “name” })public class Person
@JsonCreator 用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。 示例: @JsonCreator public Person(@JsonProperty(“name”)String name) {…}
@JsonAnySetter 用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); }
@JsonAnyGetter 用于方法 ,获取所有未序列化的属性public Map<String, Object> any() { return map; } ;

Read + Write注解

Jackson包含一组注解,这些注解会影响从JSON读取Java对象以及将Java对象写入JSON。 我将这些注解称为“读+写注解”。 以下各节将更详细地介绍Jackson的读写注解


@JsonIgnore

Jackson注解@JsonIgnore用于告诉Jackson忽略Java对象的某个属性(字段)。 在将JSON读取到Java对象中以及将Java对象写入JSON时,都将忽略该属性。

这是使用@JsonIgnore注解的示例

Person实体类

package cn.wideth.entity.domain;import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 人的基* 本信息*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {//使用了@JsonIgnore注解,id属性不会再返回给前端了@JsonIgnoreprivate Integer id;private String  name;private String  sex;private String  address;}

Controller调用

package cn.wideth.controller;import cn.wideth.entity.domain.Person;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;@RestController
@RequestMapping("/json")
@Api(tags = "JSON注解使用测试")
public class PersonController {// 查询参数@GetMapping("getPersonInfo")public List<Person> getPersonInfo() {List<Person> data = new ArrayList<>();Person p1 = new Person(1,"张三","男","上海");Person p2 = new Person(2,"李四","男","北京");Person p3 = new Person(3,"王五","男","杭州");data.add(p1);data.add(p2);data.add(p3);return data;}
}

程序结果


Person类的id属性使用了@JsonIgnore注解,不会再返回给前端了


@JsonIgnoreProperties

@JsonIgnoreProperties Jackson注解用于指定要忽略的类的属性列表@JsonIgnoreProperties注解放置在类声明上方,而不是要忽略的各个属性(字段)上方。

这是如何使用@JsonIgnoreProperties注解的示例

Person实体类

package cn.wideth.entity.domain;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 人的基* 本信息*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties({"id", "name"})
public class Person {private Integer id;private String  name;private String  sex;private String  address;}

测试结果


@JsonIgnoreType

@JsonIgnoreType Jackson注解用于将整个类型(类)标记为在使用该类型的任何地方都将被忽略。

这是一个示例,展示如何使用@JsonIgnoreType注解

import com.fasterxml.jackson.annotation.JsonIgnoreType;public class PersonIgnoreType {@JsonIgnoreTypepublic 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实例将被忽略。


@JsonAutoDetect

Jackson注解@JsonAutoDetect用于告诉Jackson在读写对象时包括非public修饰的属性。

这是一个示例类,展示如何使用@JsonAutoDetect注解

import com.fasterxml.jackson.annotation.JsonAutoDetect;@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的读取。 我称这些为“读注解”。 以下各节介绍了Jackson的读注解。


@JsonSetter

Jackson注解@JsonSetter用于告诉Jackson,当将JSON读入对象时,应将此setter方法的名称与JSON数据中的属性名称匹配。 如果Java类内部使用的属性名称与JSON文件中使用的属性名称不同,这个注解就很有用了。

以下Person类用personId名称对应JSON中名为id的字段

Person实体类

package cn.wideth.entity.domain;import com.fasterxml.jackson.annotation.JsonSetter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 人的基* 本信息*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {//在序列化的时候使用id来替换personId@JsonSetter("id")private Integer personId;private String  name;private String  sex;private String  address;}

测试程序结果


@JsonAnySetter

Jackson注解@JsonAnySetter表示Jackson为JSON对象中所有无法识别的字段调用相同的setter方法。 “无法识别”是指尚未映射到Java对象中的属性或设置方法的所有字段。

Phone实体类

package cn.wideth.entity.domain;import com.fasterxml.jackson.annotation.JsonAnySetter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.Map;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Phone {private String id;private String model;/*** 没有匹配上的反序列化属性,放到这里* @param key* @param value*/@JsonAnySetterprivate Map<String,Object> other = new HashMap<>();
}

测试程序

package cn.wideth.entity.domain;import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import java.util.HashMap;
import java.util.Map;public class Main {@SneakyThrowspublic static void main(String[] args) {Map<String,Object> map = new HashMap<>();map.put("id","abdae");map.put("name","我的");map.put("model","nokia");map.put("size","6.0");ObjectMapper mapper = new ObjectMapper();String s = mapper.writeValueAsString(map);Phone phone = mapper.readValue(s, Phone.class);System.out.println(phone);}
}

测试程序结果


@JsonCreator

Jackson注解@JsonCreator用于告诉Jackson该Java对象具有一个构造函数(“创建者”),该构造函数可以将JSON对象的字段与Java对象的字段进行匹配。

@JsonCreator注解在无法使用@JsonSetter注解的情况下很有用。 例如,不可变对象没有任何设置方法,因此它们需要将其初始值注入到构造函数中。

以这个PersonImmutable类为例

public class PersonImmutable {private long   id   = 0;private String name = null;public PersonImmutable(long id, String name) {this.id = id;this.name = name;}public long getId() {return id;}public String getName() {return name;}}

要告诉Jackson应该调用PersonImmutable的构造函数,我们必须在构造函数中添加@JsonCreator注解。 但是,仅凭这一点还不够。 我们还必须注解构造函数的参数,以告诉Jackson将JSON对象中的哪些字段传递给哪些构造函数参数。

添加了@JsonCreator和@JsonProperty注解的PersonImmutable类的示例如下:

public class PersonImmutable {private long   id   = 0;private String name = null;@JsonCreatorpublic PersonImmutable(@JsonProperty("id")  long id,@JsonProperty("name") String name  ) {this.id = id;this.name = name;}public long getId() {return id;}public String getName() {return name;}}

请注意,构造函数上方的注解以及构造函数参数之前的注解。 现在,Jackson能够从此JSON对象创建PersonImmutable:

{"id"   : 1234,"name" : "John"
}

@JacksonInject

Jackson注解@JacksonInject用于将值注入到解析的对象中,而不是从JSON中读取这些值。 例如,假设正在从各种不同的源下载Person JSON对象,并且想知道给定Person对象来自哪个源。 源本身可能不包含该信息,但是可以让Jackson将其注入到根据JSON对象创建的Java对象中。

要将Java类中的字段标记为需要由Jackson注入其值的字段,请在该字段上方添加@JacksonInject注解。

这是一个示例PersonInject类,在属性上方添加了@JacksonInject注解

public class PersonInject {public long   id   = 0;public String name = null;@JacksonInjectpublic String source = null;}

为了让Jackson将值注入属性,需要在创建Jackson ObjectMapper时做一些额外的工作。

这是让Jackson将值注入Java对象的过程:

InjectableValues inject = new InjectableValues.Std().addValue(String.class, "jenkov.com");
PersonInject personInject = new ObjectMapper().reader(inject).forType(PersonInject.class).readValue(new File("data/person.json"));

请注意,如何在InjectableValues addValue()方法中设置要注入到source属性中的值。 还要注意,该值仅绑定到字符串类型-而不绑定到任何特定的字段名称。 @JacksonInject注解指定将值注入到哪个字段。

如果要从多个源下载人员JSON对象,并为每个源注入不同的源值,则必须为每个源重复以上代码。


@JsonDeserialize

Jackson注解@JsonDeserialize用于为Java对象中给定的属性指定自定义反序列化器类。

例如,假设想优化布尔值false和true的在线格式,使其分别为0和1。

首先,需要将@JsonDeserialize注解添加到要为其使用自定义反序列化器的字段。 这是将@JsonDeserialize注解添加到字段的示例:

public class PersonDeserialize {public long    id      = 0;public String  name    = null;@JsonDeserialize(using = OptimizedBooleanDeserializer.class)public boolean enabled = false;
}

其次,这是@JsonDeserialize注解中引用的OptimizedBooleanDeserializer类的实例:

public class OptimizedBooleanDeserializerextends JsonDeserializer<Boolean> {@Overridepublic Boolean deserialize(JsonParser jsonParser,DeserializationContext deserializationContext) throwsIOException, JsonProcessingException {String text = jsonParser.getText();if("0".equals(text)) return false;return true;}
}

请注意,OptimizedBooleanDeserializer类使用通用类型Boolean扩展了JsonDeserializer。 这样做会使deserialize()方法返回一个布尔对象。 如果要反序列化其他类型(例如java.util.Date),则必须在泛型括号内指定该类型。

可以通过调用jsonParser参数的getText()方法来获取要反序列化的字段的值。 然后,可以将该文本反序列化为任何值,然后输入反序列化程序所针对的类型(在此示例中为布尔值)。

最后,需要查看使用自定义反序列化器和@JsonDeserializer注解反序列化对象的格式:

PersonDeserialize person = objectMapper.reader(PersonDeserialize.class).readValue(new File("data/person-optimized-boolean.json"));

注意,我们首先需要如何使用ObjectMapper的reader()方法为PersonDeserialize类创建一个阅读器,然后在该方法返回的对象上调用readValue()。


Write注解

Jackson还包含一组注解,这些注解可以影响Jackson将Java对象序列化(写入)到JSON的方式。 以下各节将介绍这些写(序列化)注解中的每一个。


@JsonInclude

Jackson注解@JsonInclude告诉Jackson仅在某些情况下包括属性。 例如,仅当属性为非null,非空或具有非默认值时,才应包括该属性。 这是显示如何使用@JsonInclude注解的示例:

import com.fasterxml.jackson.annotation.JsonInclude;@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class PersonInclude {public long  personId = 0;public String name     = null;}

如果为该示例设置的值是非空的,则此示例将仅包括name属性,这意味着不为null且不是空字符串。

@JsonInclude注解的一个更通俗的名称应该是@JsonIncludeOnlyWhen,但是写起来会更长。


@JsonGetter

@JsonGetter Jackson注解用于告诉Jackson,应该通过调用getter方法而不是通过直接字段访问来获取某个字段值。 如果您的Java类使用jQuery样式的getter和setter名称,则@JsonGetter注解很有用。

例如,您可能拥有方法personId()和personId(long id),而不是getPersonId()和setPersonId()。

这是一个名为PersonGetter的示例类,它显示了@JsonGetter注解的用法:

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; }}

如您所见,personId()方法带有@JsonGetter注解。 @JsonGetter注解上设置的值是JSON对象中应使用的名称。 因此,用于JSON对象中personId的名称是id。 生成的JSON对象如下所示:

{"id":0}

还要注意,personId(long personId)方法使用@JsonSetter注解进行注解,以使Jackson识别为与JSON对象中的id属性匹配的设置方法。 从JSON读取Java对象时使用@JsonSetter注解-将Java对象写入JSON时不使用。 为了完整起见,仅包含@JsonSetter注解。


@JsonAnyGetter

@JsonAnyGetter Jackson注解使您可以将Map用作要序列化为JSON的属性的容器。 这是在Java类中使用@JsonAnyGetter注解的示例:

public class PersonAnyGetter {private Map<String, Object> properties = new HashMap<>();@JsonAnyGetterpublic Map<String, Object> properties() {return properties;}
}

当看到@JsonAnyGetter注解时,Jackson将从@JsonAnyGetter注解的方法中获取返回的Map,并将该Map中的每个键值对都视为一个属性。 换句话说,Map中的所有键值对都将作为PersonAnyGetter对象的一部分序列化为JSON。


@JsonPropertyOrder

@JsonPropertyOrder Jackson注解可用于指定将Java对象的字段序列化为JSON的顺序。 这是显示如何使用@JsonPropertyOrder注解的示例:

@JsonPropertyOrder({"name", "personId"})
public class PersonPropertyOrder {public long  personId  = 0;public String name     = null;}

通常,Jackson会按照在类中找到的顺序序列化PersonPropertyOrder中的属性。 但是,@JsonPropertyOrder注解指定了不同的顺序,在序列化的JSON输出中,name属性将首先出现,personId属性将随后出现。


@JsonRawValue

@JsonRawValue Jackson注解告诉Jackson该属性值应直接写入JSON输出。 如果该属性是字符串,Jackson通常会将值括在引号中,但是如果使用@JsonRawValue属性进行注解,Jackson将不会这样做。

为了更清楚@JsonRawValue的作用,看看没有使用@JsonRawValue的此类:

public class PersonRawValue {public long   personId = 0;public String address  = "$#";
}

Jackson会将其序列化为以下JSON字符串:

{"personId":0,"address":"$#"}

现在,我们将@JsonRawValue添加到address属性,如下所示:

public class PersonRawValue {public long   personId = 0;@JsonRawValuepublic String address  = "$#";
}

现在,当对地址属性进行序列化时,杰克逊将省略引号。 因此,序列化的JSON如下所示:

{"personId":0,"address":$#}

当然它是无效的JSON,那么为什么要这么做呢?

如果address属性包含一个JSON字符串,那么该JSON字符串将被序列化为最终的JSON对象,作为JSON对象结构的一部分,而不仅是序列化为JSON对象的address字段中的字符串。

要查看其工作原理,让我们像下面这样更改address属性的值:

public class PersonRawValue {public long   personId = 0;@JsonRawValuepublic String address  ="{ \"street\" : \"Wall Street\", \"no\":1}";}

Jackson会将其序列化为以下JSON:

{"personId":0,"address":{ "street" : "Wall Street", "no":1}}

请注意,JSON字符串现在如何成为序列化JSON结构的一部分。

没有@JsonRawValue注解,Jackson会将对象序列化为以下JSON:

{"personId":0,"address":"{ \"street\" : \"Wall Street\", \"no\":1}"}

请注意,address属性的值现在如何用引号引起来,并且值内的所有引号均被转义。


@JsonValue

Jackson注解@JsonValue告诉Jackson,Jackson不应该尝试序列化对象本身,而应在对象上调用将对象序列化为JSON字符串的方法。 请注意,Jackson将在自定义序列化返回的String内转义任何引号,因此不能返回例如 完整的JSON对象。 为此,应该改用@JsonRawValue(请参阅上一节)。

@JsonValue注解已添加到Jackson调用的方法中,以将对象序列化为JSON字符串。 这是显示如何使用@JsonValue注解的示例:

public class PersonValue {public long   personId = 0;public String name = null;@JsonValuepublic String toJson(){return this.personId + "," + this.name;}}

要求Jackson序列化PersonValue对象所得到的输出是:

"0,null"

引号由Jackson添加。 请记住,对象返回的值字符串中的所有引号均会转义。


@JsonSerialize

@JsonSerialize Jackson注解用于为Java对象中的字段指定自定义序列化程序。 这是一个使用@JsonSerialize注解的Java类示例:

public class PersonSerializer {public long   personId = 0;public String name     = "John";@JsonSerialize(using = OptimizedBooleanSerializer.class)public boolean enabled = false;
}

注意启用字段上方的@JsonSerialize注解。

OptimizedBooleanSerializer将序列的真值序列化为1,将假值序列化为0。这是代码:

public class OptimizedBooleanSerializer extends JsonSerializer<Boolean> {@Overridepublic void serialize(Boolean aBoolean, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {if(aBoolean){jsonGenerator.writeNumber(1);} else {jsonGenerator.writeNumber(0);}}
}

本文小结

本文详细介绍了Jackson中的各个注解。

Jackson注解详解相关推荐

  1. 2.Spring Boot 中Json的使用,Jackson注解详解

    一.前言 1.介绍 我们常在项目中使用的Json转换工具是fastjson,事实上spring本身集成了非常优秀的json工具,分别为Jackson,Gson,JSON-B,但是官方项目中默认推荐使用 ...

  2. Spring data JPA 之 Jackson 在实体里面的注解详解

    8 Spring data JPA 之 Jackson 在实体里面的注解详解 经过前⾯课时的讲解,相信你已经对实体⾥⾯的 JPA 注解有了⼀定的了解,但是实际⼯作中你会发现实体⾥⾯不仅有 JPA 的注 ...

  3. 26.SpringBoot事务注解详解

    转自:https://www.cnblogs.com/kesimin/p/9546225.html @Transactional spring 事务注解 1.简单开启事务管理 @EnableTrans ...

  4. mybatis注解详解

    mybatis注解详解 首 先当然得下载mybatis-3.0.5.jar和mybatis-spring-1.0.1.jar两个JAR包,并放在WEB-INF的lib目录下 (如果你使用maven,则 ...

  5. 开启注解缓存_Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  6. spring-boot注解详解(一)

    spring-boot注解详解(一) @SpringBootApplication @SpringBootApplication = (默认属性)@Configuration + @EnableAut ...

  7. Spring零配置之@Configuration注解详解

    转载自 Spring零配置之@Configuration注解详解 @Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而 ...

  8. Spring Boot注解详解

    文章目录 使用注解的优势 注解详解(配备了完善的释义) 注解列表如下 JPA注解 springMVC相关注解 全局异常处理 项目中具体配置解析和使用环境 使用注解的优势 采用纯java代码,不在需要配 ...

  9. 【SpringBoot 】SpringBoot注解详解

    [SpringBoot ]SpringBoot注解详解 一.注解(annotations)列表  @SpringBootApplication:包含了@ComponentScan.@Configura ...

最新文章

  1. python面向对象编程的优点-Python面向对象编程
  2. 画一个皮卡丘项目小结(4)
  3. ubuntu装机配置相关
  4. word中光标选择一列文字_Word中文字排版对齐很难?只因你没掌握这几招排版技巧!...
  5. 基于注解的方式配置bean
  6. 利剑无意之面试题(二)
  7. python从数分到数编(part1)--基础
  8. mysql字符串用法
  9. 适合做手机铃声的81首歌_“想下载这首歌作为你的手机铃声吗?”
  10. 期货市场计算机分析指南在线,期货市场计算机分析指南
  11. java int转bitmap_Java Base64位编码与String字符串的相互转换,Base64与Bitmap的相互转换实例代码...
  12. 立刻、马上对你的电脑做这三件事!
  13. Linux并发程序课程设计报告,网络操作系统课程设计--进程机制与并发程序设计-linux下生产者与消费者的问题实现.doc...
  14. python输出文本内容_python如何输出文件内容
  15. Android项目同步,如何通过gradle任务同步Android项目?
  16. Ubuntu中的回车与换行
  17. poi 导出excel 中合并单元格
  18. MapGIS干货|数据投影生成地质图的8个视频教程
  19. 运维技术相关基础面试
  20. JWT Token、ID Token、Access Token、Refresh Token

热门文章

  1. Mqtt开发java开发-消息服务mns中的一些坑
  2. 根文件系统制作 -- Kernel panic - not syncing
  3. python 拟合圆心_圆的散点拟合, 已知圆的采样点, 求圆的圆心和半径.
  4. 计算机网络配适器型号在哪里看,网络适配器型号在哪看_怎么更换网络适配器...
  5. Python数据分析与机器学习21- 逻辑回归项目实战5-阀值
  6. Python使用QT播放视频
  7. 各大牛逼网站推荐系统
  8. 【报错解决办法】bad restore file magic number (file may be corrupted) -- no data loaded
  9. nove8se支持鸿蒙,华为nova8se处理器用的什么处理器_华为nova8se另个版本分别用什么处理器...
  10. koa2的脚手架koa-generator