搞定Jackson序列化与常用注解

简介 Jackson是Java的一套数据处理工具,包括一流的JSON解析/生成库,匹配数据绑定库(用于类与JSON串之间的转换),和其他数据格式模块,以处理Avro、BSON、CBOR、CSV、Smile、(Java) Properties、Protobuf、XML或YAML编码的数据。
三个核心模块

  • Streaming (jackson-core包):定义了低级流式API,包括了特定json的实现。
  • Annotations (jackson-annotations包):包含标准的Jackson注解。
  • Databind (jackson-databind包):实现了数据绑定,依赖于Streaming和Annotations。(导入jackson-databind包会自动导入其他两个包)
什么是序列化和反序列化
  • 序列化(serialization):JSON对象 -> JSON字符串
  • 反序列化(deserialization):JSON字符串 -> JSON对象
Jackson的序列化和反序列化
  • Jackson默认序列化public的属性和getter方法,所以如果是public的属性可以不需要getter方法,但如果是private的属性,就需要有标准的getter方法。
  • Jackson的反序列化public的属性和getter方法,所以如果是public的属性可以不需要setter方法,但如果是private的属性,就需要有标准的setter方法。Jackson反序列化时默认使用无参构造方法创建对象。
引入依赖 一般情况下
com.fasterxml.jackson.core jackson-databind 2.11.1

引入jackson-databind会关联引入jackson-annotations和jackson-core。
SpringBoot下
spring-boot-starter-web包中自带了jackson的核心类库,所以不用再手动引入。
ObjectMapper使用 在Jackson中使用ObjectMapper对象来进行序列化和反序列化操作。
下面使用Car来作为操作演示的类:
public class Car { private String color; private String type; // standard getters setters }

序列化操作
ObjectMapper objectMapper = new ObjectMapper(); Car car = new Car("yellow", "renault"); objectMapper.writeValue(new File("target/car.json"), car); // 序列化到文件 String carAsString = objectMapper.writeValueAsString(car); // 序列化成String

反序列化操作 【搞定Jackson序列化与常用注解】JSON 反序列化成 Java Object
String json = "{\"color\":\"yellow\",\"type\":\"renault\"}"; ObjectMapper mapper = new ObjectMapper(); Car car = mapper.readValue(json, Car.class);

JSON 反序列化成 Jackson的JsonNode类型
String json = "{\"color\":\"yellow\",\"type\":\"renault\"}"; ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(json); String type = jsonNode.get("type").asText();

JSNO数组 反序列化成 Java List类型
// 方式1(推荐) String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){}); // 方式2 String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);

JSON 反序列化成 Map类型
String json = "{ \"color\" : \"Black\", \"type\" : {\"a\": 22}, \"arr\":[\"aa\", \"bb\"] }"; Map map = new ObjectMapper().readValue(json, new TypeReference() {}); System.out.println("map = " + map); String color = (String) map.get("color"); System.out.println("color = " + color); Map type= (Map) map.get("type"); Integer a = (Integer) type.get("a"); System.out.println("a = " + a); List arr = (List) map.get("arr"); System.out.println("arr = " + arr);

Jackson注解 下面按照功能划分了Jackson的注解,并给予了简要的文字解释。具体注解使用示例,可以参考文章Jackson Annotation Examples
Jackson的序列化注解
  • @JsonAnyGetter:作用于Map字段的getter方法上,可以将该Map字段中的键值对作为类的标准属性来序列化。例如:@JsonAnyGetter
  • @JsonGetter:以某个将方法标记为getter方法,是@JsonProperty的替代方法。例如:@JsonGetter("name")
  • @JsonPropertyOrder:指定序列化时属性的顺序。例如:@JsonPropertyOrder({ "name", "id" })、@JsonPropertyOrder(alphabetic=true)
  • @JsonRawValue:指定属性按照原生字符串的形式进行序列化,即不会对字符串进行转义,在需要嵌入Json字符串时很有用。例如:@JsonRawValue
  • @JsonValue:指定使用某个方法来序列化整个实例。例如:@JsonValue
  • @JsonRootName:当开启了SerializationFeature.WRAP_ROOT_VALUE时,用于指定包装实体的名称。例如:@JsonRootName(value = "https://www.it610.com/article/user")
  • @JsonSerialize:表示在序列化时使用指定的自定义序列化器。例如:@JsonSerialize(using = CustomDateSerializer.class)
Jackson的反序列化注解
  • @JsonCreator:作用于类的构造方法或工厂方法上,表示用于反序列化生成对象,当JSON与实体不完全匹配时很有用。例如:@JsonCreator
  • @JacksonInject:表示属性将从注入中获取其值,而不是从JSON数据中。例如:@JacksonInject
  • @JsonAnySetter:表示反序列化时可以将未知属性用Map接收。例如:@JsonAnySetter
  • @JsonSetter:将方法标记为setter方法,是@JsonProperty的一种替代方法。当JSON与属性值不匹配时很有用。例如:@JsonSetter("name")
  • @JsonDeserialize:表示使用自定义反序列化器。例如:@JsonDeserialize(using = CustomDateDeserializer.class)
  • @JsonAlias:在反序列化期间为属性定义一个或多个可选名称。例如:@JsonAlias({ "fName", "f_name" })
Jackson的属性包含注解
  • @JsonIgnoreProperties:类级别注解,表示某些类的字段在序列化和反序列化时会被忽略。有个ignoreUnknown的配置,为true时会忽略反序列化时未知的属性,默认为false,即当有未知属性时会抛出异常。例如:@JsonIgnoreProperties(value = https://www.it610.com/article/{"id"}, ignoreUnknown = true)
  • @JsonIgnore:字段级别注解,表示该字段会被Jackson忽略。例如:@JsonIgnore
  • @JsonIgnoreType:类级别注解,表示该类的所有字段都会被Jackson忽略。例如:@JsonIgnoreType
  • @JsonInclude:在反序列化时,可用于排除带有空/空/默认值的属性。例如:@JsonInclude(value = https://www.it610.com/article/JsonInclude.Include.NON_NULL)
  • @JsonAutoDetect:可以改变默认的字段可见性。默认不可见private字段。例如:@JsonAutoDetect(fieldVisibility = Visibility.ANY)
  • @JsonTypeInfo、@JsonSubTypes、@JsonTypeName:用于处理多态的注解。
Jackson的通用注解
  • @JsonProperty:用来指定序列化和反序列化的属性名映射。例如:@JsonProperty("name")
  • @JsonFormat:在序列化和反序列化Date/Time值时指定格式,默认的时区是格林威治时间。例如:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  • @JsonUnwrapped:表示在序列化/反序列化时应该取消对象的包装。例如:@JsonUnwrapped
  • @JsonView:可用于序列化/反序列化时字段的可见性问题。
  • @JsonManagedReference, @JsonBackReference:可用于处理循环依赖问题。
  • @JsonIdentityInfo:可用于处理循环依赖问题。
  • @JsonFilter:在序列化时指定Filter。
  • @JacksonAnnotationsInside:用于自定义注解。
Jackson Feature 常用的Jackson特性开关:
  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:反序列化时有未知属性则失败。默认是。
  • SerializationFeature.WRAP_ROOT_VALUE:指定序列化时包装根对象。默认否。
  • MapperFeature.USE_ANNOTATIONS:使用注解,默认是。
可以使用mapper的configure()、enable()、disable()来配置特性,例如:
ObjectMapper mapper = new ObjectMapper(); mapper.disable(SerializationFeature.WRAP_ROOT_VALUE); mapper.disable(MapperFeature.USE_ANNOTATIONS);

@JsonFormat和@DateTimeFormat的区别 @JsonFormat
是Jackson的注解,在JSON进行序列化和反序列化Date/Time值时指定格式。由于Jackson默认的时区是格林威治时间,而我们是在东八区上,所以时间会比实际我们想得到的时间少八个小时,所以我们需要设置指定的时区:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

在SpringBoot中,可以通过配置文件统一配置时间格式和时区
// 配置文件统一配置 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8

@DateTimeFormat
是Spring的注解,用于将Get请求中URL路径中的参数格式化为Date类型。不能指定时区,默认就是当前时区
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

参考资料
  • 官方介绍网站
  • 官方文档网站
  • Jackson快速入门
  • baeldung英文教程

    推荐阅读