SpringBoot的Jackson最全使用详解
在Spring Boot项目中,Jackson是默认的JSON处理库,用于对象与JSON之间的序列化和反序列化。本文将详细介绍Jackson在Spring Boot下的各种使用方法,包括基本配置、注解使用、自定义序列化器和反序列化器、以及处理复杂数据类型等。
1. 导入依赖
在Spring Boot项目中,通常不需要手动导入Jackson的依赖,因为spring-boot-starter-web
已经包含了这些依赖。但如果你需要单独引入,可以在pom.xml
文件中添加以下依赖:
<!-- Jackson核心库 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
2. 全局配置
在application.properties
或application.yml
文件中,可以对Jackson进行全局配置,例如设置日期格式、时区等。
application.yml
spring:
jackson:
# 设置日期格式
date-format: yyyy-MM-dd HH:mm:ss
# 设置时区
time-zone: Asia/Shanghai
# 设置默认属性包含方式,例如非空
default-property-inclusion: non_null
serialization:
# 设置序列化时是否格式化输出
indent-output: true
deserialization:
# 设置反序列化时是否忽略未知属性
fail-on-unknown-properties: false
parser:
# 设置解析器是否允许未转义的控制字符
allow-unquoted-control-chars: true
# 设置解析器是否允许单引号
allow-single-quotes: true
3. 自定义配置
除了通过配置文件进行全局配置外,还可以通过代码自定义配置Jackson的ObjectMapper
。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
// 设置日期格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 设置时区
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 设置序列化时是否格式化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
// 设置反序列化时是否忽略未知属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 设置解析器是否允许未转义的控制字符
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
// 设置解析器是否允许单引号
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 添加Java 8时间模块支持
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
}
4. 注解使用
Jackson提供了多种注解来控制序列化和反序列化的行为,以下是一些常用的注解及其用法。
@JsonIgnore
:忽略字段的序列化和反序列化。@JsonProperty
:指定字段的JSON键名。@JsonFormat
:指定日期格式。@JsonInclude
:控制字段的序列化条件。@JsonView
:控制视图。@JsonAlias
:为反序列化期间要接受的属性定义一个或多个替代名称。@JsonPropertyOrder
:指定字段的序列化顺序。@JsonRawValue
:将字段值作为原始JSON字符串处理。@JsonAnyGetter
和@JsonAnySetter
:处理动态属性。
示例实体类
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.Date;
@JsonInclude(JsonInclude.Include.NON_NULL) // 忽略值为null的属性
@JsonPropertyOrder({"name", "age", "email"}) // 控制属性的序列化顺序
public class User {
@JsonProperty("user_name") // 设置属性的JSON名称
private String name;
private int age;
@JsonIgnore // 忽略此属性的序列化和反序列化
private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") // 设置日期格式和时区
private Date createdDate;
@JsonProperty("user_email") // 设置属性的JSON名称
private String email;
@JsonInclude(JsonInclude.Include.NON_NULL) // 控制字段的序列化条件
private String email;
@JsonRawValue // 将字段值作为原始JSON字符串处理
private String rawJson;
private Map<String, Object> additionalProperties;
@JsonAnyGetter
public Map<String, Object> any() {
return additionalProperties;
}
@JsonAnySetter
public void set(String name, Object value) {
if (additionalProperties == null) {
additionalProperties = new HashMap<>();
}
additionalProperties.put(name, value);
}
// 其他构造函数、getter和setter省略
}
5. 序列化和反序列化
序列化对象为JSON字符串
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private ObjectMapper objectMapper;
@GetMapping("/serialize")
public String serialize() throws Exception {
// 创建一个Java对象
User user = new User();
user.setName("张三");
user.setAge(30);
user.setPassword("123456");
user.setCreatedDate(new Date());
user.setEmail("zhangsan@example.com");
// 序列化Java对象为JSON字符串
String jsonString = objectMapper.writeValueAsString(user);
return "序列化后的JSON字符串: " + jsonString;
}
}
反序列化JSON字符串为对象
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private ObjectMapper objectMapper;
@PostMapping("/deserialize")
public User deserialize(@RequestBody String jsonString) throws Exception {
// 反序列化JSON字符串为Java对象
User user = objectMapper.readValue(jsonString, User.class);
return user;
}
}
6. 自定义序列化器和反序列化器
有时候默认的序列化和反序列化行为可能不满足需求,可以通过自定义序列化器和反序列化器来实现更复杂的功能。
自定义序列化器
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CustomDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
自定义反序列化器
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CustomDateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
return dateFormat.parse(p.getValueAsString());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
使用自定义序列化器和反序列化器
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import java.util.Date;
@Data
public class User {
private String name;
@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date registerDate;
}
7. 处理复杂数据类型
7.1 List序列化和反序列化
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
@RestController
public class UserController {
@Autowired
private ObjectMapper objectMapper;
@GetMapping("/serialize-list")
public String serializeList() throws Exception {
// 创建一个Java对象列表
List<User> users = Arrays.asList(
new User("张三", 30, "123456", new Date(), "zhangsan@example.com"),
new User("李四", 25, "654321", new Date(), "lisi@example.com")
);
// 序列化Java对象列表为JSON字符串
String jsonString = objectMapper.writeValueAsString(users);
return "序列化后的JSON字符串: " + jsonString;
}
@PostMapping("/deserialize-list")
public List<User> deserializeList(@RequestBody String jsonString) throws Exception {
// 反序列化JSON字符串为Java对象列表
List<User> users = objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));
return users;
}
}
7.2 Map序列化和反序列化
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class UserController {
@Autowired
private ObjectMapper objectMapper;
@GetMapping("/serialize-map")
public String serializeMap() throws Exception {
// 创建一个Map
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 30);
map.put("email", "zhangsan@example.com");
// 序列化Map为JSON字符串
String jsonString = objectMapper.writeValueAsString(map);
return "序列化后的JSON字符串: " + jsonString;
}
@PostMapping("/deserialize-map")
public Map<String, Object> deserializeMap(@RequestBody String jsonString) throws Exception {
// 反序列化JSON字符串为Map
Map<String, Object> resultMap = objectMapper.readValue(jsonString, Map.class);
return resultMap;
}
}
7.3 枚举类型序列化和反序列化
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public enum Status {
ACTIVE("active"),
INACTIVE("inactive");
private String value;
Status(String value) {
this.value = value;
}
@JsonCreator
public static Status fromValue(@JsonProperty("value") String value) {
for (Status status : values()) {
if (status.getValue().equals(value)) {
return status;
}
}
throw new IllegalArgumentException("Unknown enum value: " + value);
}
public String getValue() {
return value;
}
}
7.3 使用枚举类型
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private ObjectMapper objectMapper;
@GetMapping("/serialize-enum")
public String serializeEnum() throws Exception {
// 创建一个包含枚举类型的Java对象
User user = new User();
user.setStatus(Status.ACTIVE);
// 序列化Java对象为JSON字符串
String jsonString = objectMapper.writeValueAsString(user);
return "序列化后的JSON字符串: " + jsonString;
}
@PostMapping("/deserialize-enum")
public User deserializeEnum(@RequestBody String jsonString) throws Exception {
// 反序列化JSON字符串为Java对象
User user = objectMapper.readValue(jsonString, User.class);
return user;
}
}
7.4 处理嵌套对象
Jackson可以轻松处理嵌套对象的序列化和反序列化。
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
@Data
public class Address {
private String street;
private String city;
private String zipCode;
}
@Data
public class User {
private String name;
private Address address;
}
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// 创建一个嵌套对象
Address address = new Address("123 Main St", "Springfield", "12345");
User user = new User("张三", address);
// 序列化嵌套对象为JSON字符串
String jsonString = mapper.writeValueAsString(user);
System.out.println("序列化后的JSON字符串: " + jsonString);
// 反序列化JSON字符串为嵌套对象
User deserializedUser = mapper.readValue(jsonString, User.class);
System.out.println("反序列化后的嵌套对象: " + deserializedUser);
}
}
7.5 处理循环引用
在处理包含循环引用的对象时,可以使用@JsonIdentityInfo
注解来避免无限递归。
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import lombok.Data;
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class User {
private Long id;
private String name;
private User friend;
}
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// 创建循环引用对象
User user1 = new User(1L, "张三", null);
User user2 = new User(2L, "李四", user1);
user1.setFriend(user2);
// 序列化循环引用对象为JSON字符串
String jsonString = mapper.writeValueAsString(user1);
System.out.println("序列化后的JSON字符串: " + jsonString);
// 反序列化JSON字符串为循环引用对象
User deserializedUser = mapper.readValue(jsonString, User.class);
System.out.println("反序列化后的循环引用对象: " + deserializedUser);
}
}
7.6 处理多态类型
Jackson可以通过@JsonTypeInfo
和@JsonSubTypes
注解来处理多态类型。
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
interface Animal {}
@Data
class Dog implements Animal {
private String breed;
}
@Data
class Cat implements Animal {
private String color;
}
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// 创建多态对象
Animal dog = new Dog("German Shepherd");
Animal cat = new Cat("Black");
// 序列化多态对象为JSON字符串
String jsonStringDog = mapper.writeValueAsString(dog);
String jsonStringCat = mapper.writeValueAsString(cat);
System.out.println("序列化后的JSON字符串 (Dog): " + jsonStringDog);
System.out.println("序列化后的JSON字符串 (Cat): " + jsonStringCat);
// 反序列化JSON字符串为多态对象
Animal deserializedDog = mapper.readValue(jsonStringDog, Animal.class);
Animal deserializedCat = mapper.readValue(jsonStringCat, Animal.class);
System.out.println("反序列化后的多态对象 (Dog): " + deserializedDog);
System.out.println("反序列化后的多态对象 (Cat): " + deserializedCat);
}
}
7.7 处理异常
在处理JSON数据时,可能会遇到各种异常。可以通过捕获这些异常来处理错误情况。
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
// 错误的JSON字符串
String jsonString = "{\"name\": \"张三\", \"age\": \"not a number\"}";
try {
// 尝试反序列化JSON字符串为Java对象
Person person = mapper.readValue(jsonString, Person.class);
System.out.println("反序列化后的Java对象: " + person);
} catch (JsonMappingException e) {
System.out.println("JSON映射异常: " + e.getMessage());
} catch (Exception e) {
System.out.println("其他异常: " + e.getMessage());
}
}
}
通过本文的介绍,你应该对Spring Boot下Jackson的各种使用方法有了全面的了解。从基础配置到高级功能,Jackson提供了丰富的API和灵活的配置选项,使得开发者可以根据具体需求进行定制。希望本文能帮助你在项目开发中更加高效地利用Jackson进行JSON数据处理。