Jackson注解详解
本文来说下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注解详解相关推荐
- 2.Spring Boot 中Json的使用,Jackson注解详解
一.前言 1.介绍 我们常在项目中使用的Json转换工具是fastjson,事实上spring本身集成了非常优秀的json工具,分别为Jackson,Gson,JSON-B,但是官方项目中默认推荐使用 ...
- Spring data JPA 之 Jackson 在实体里面的注解详解
8 Spring data JPA 之 Jackson 在实体里面的注解详解 经过前⾯课时的讲解,相信你已经对实体⾥⾯的 JPA 注解有了⼀定的了解,但是实际⼯作中你会发现实体⾥⾯不仅有 JPA 的注 ...
- 26.SpringBoot事务注解详解
转自:https://www.cnblogs.com/kesimin/p/9546225.html @Transactional spring 事务注解 1.简单开启事务管理 @EnableTrans ...
- mybatis注解详解
mybatis注解详解 首 先当然得下载mybatis-3.0.5.jar和mybatis-spring-1.0.1.jar两个JAR包,并放在WEB-INF的lib目录下 (如果你使用maven,则 ...
- 开启注解缓存_Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
- spring-boot注解详解(一)
spring-boot注解详解(一) @SpringBootApplication @SpringBootApplication = (默认属性)@Configuration + @EnableAut ...
- Spring零配置之@Configuration注解详解
转载自 Spring零配置之@Configuration注解详解 @Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而 ...
- Spring Boot注解详解
文章目录 使用注解的优势 注解详解(配备了完善的释义) 注解列表如下 JPA注解 springMVC相关注解 全局异常处理 项目中具体配置解析和使用环境 使用注解的优势 采用纯java代码,不在需要配 ...
- 【SpringBoot 】SpringBoot注解详解
[SpringBoot ]SpringBoot注解详解 一.注解(annotations)列表 @SpringBootApplication:包含了@ComponentScan.@Configura ...
最新文章
- python面向对象编程的优点-Python面向对象编程
- 画一个皮卡丘项目小结(4)
- ubuntu装机配置相关
- word中光标选择一列文字_Word中文字排版对齐很难?只因你没掌握这几招排版技巧!...
- 基于注解的方式配置bean
- 利剑无意之面试题(二)
- python从数分到数编(part1)--基础
- mysql字符串用法
- 适合做手机铃声的81首歌_“想下载这首歌作为你的手机铃声吗?”
- 期货市场计算机分析指南在线,期货市场计算机分析指南
- java int转bitmap_Java Base64位编码与String字符串的相互转换,Base64与Bitmap的相互转换实例代码...
- 立刻、马上对你的电脑做这三件事!
- Linux并发程序课程设计报告,网络操作系统课程设计--进程机制与并发程序设计-linux下生产者与消费者的问题实现.doc...
- python输出文本内容_python如何输出文件内容
- Android项目同步,如何通过gradle任务同步Android项目?
- Ubuntu中的回车与换行
- poi 导出excel 中合并单元格
- MapGIS干货|数据投影生成地质图的8个视频教程
- 运维技术相关基础面试
- JWT Token、ID Token、Access Token、Refresh Token
热门文章
- Mqtt开发java开发-消息服务mns中的一些坑
- 根文件系统制作 -- Kernel panic - not syncing
- python 拟合圆心_圆的散点拟合, 已知圆的采样点, 求圆的圆心和半径.
- 计算机网络配适器型号在哪里看,网络适配器型号在哪看_怎么更换网络适配器...
- Python数据分析与机器学习21- 逻辑回归项目实战5-阀值
- Python使用QT播放视频
- 各大牛逼网站推荐系统
- 【报错解决办法】bad restore file magic number (file may be corrupted) -- no data loaded
- nove8se支持鸿蒙,华为nova8se处理器用的什么处理器_华为nova8se另个版本分别用什么处理器...
- koa2的脚手架koa-generator