Springboot JSON 转换:Jackson篇

近期想整理一下 Springboot 对于处理 JSON 转换的笔记,想起了 Jackson 是 SpringMVC 默认使用的 JSON 转换器,就从 Jackson 下手,后续用到其他的在整理

本案例基于 Springboot 2.5.7 单元测试场景下进行

<!-- SpringMVC默认使用Jacson,只需要引用web启动器即可,无序单独引用Jackson --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Springboot单元测试 --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- Lombok工具类 --> <dependency>     <groupId>org.projectlombok</groupId>     <artifactId>lombok</artifactId> </dependency> <!-- Hutool工具类 --> <dependency>     <groupId>cn.hutool</groupId>     <artifactId>hutool-all</artifactId>     <version>5.8.3</version> </dependency> 

在后面的测试中会用到的实体类

@Data @NoArgsConstructor @AllArgsConstructor public class UserEntity {     private Integer id;     private String username;     private String password;     private Date birthday;     private LocalDateTime lastLoginDate;     private DeptEntity dept; }  
@Data @NoArgsConstructor @AllArgsConstructor public class DeptEntity {     private Integer id;     private String name; } 
@Data @NoArgsConstructor @AllArgsConstructor public class Result<T> {      private int code;     private String msg;     private T data;      public static <T> Result<T> success(T data) {         return new Result<>(200, "请求成功", data);     }  } 

IOC 容器中可以直接获取到 Jackson 的 ObjectMapper 实例

@SpringBootTest public class SpringTest {     @Autowired     private ObjectMapper mapper; } 

基础类型转换

简单来说就是实体类转换,无论是实体类还是实体类嵌套方法都是一样的

实体类转换

@Test void test() throws JsonProcessingException {     // 实体类     DeptEntity dept = new DeptEntity(10001, "部门A");     // 序列化     String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dept);     // 反序列化     System.out.println(mapper.readValue(json, DeptEntity.class)); } 

实体类嵌套转换

@Test void test() {     // 实体类     Date birthday = new Date();     LocalDateTime lastLoginDate = LocalDateTime.now();     DeptEntity dept = new DeptEntity(10001, "部门A");     UserEntity user = new UserEntity(10001, "用户A", null, birthday, lastLoginDate, dept);     // 序列化     String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);     // 反序列化     System.out.println(mapper.readValue(json, UserEntity.class)); } 

集合类型转换

集合转换简单了解这两种就够了,复杂一点的后面会提到

Collection 集合转换

@Test void test() throws JsonProcessingException {     // 构建List集合     List<DeptEntity> source = CollUtil.newArrayList();     for (int i = 1; i <= 5; i++) {         source.add(new DeptEntity(10000 + i, "用户" + i));     }     // 序列化     String json = mapper.writeValueAsString(source);     // 构建Type对象     CollectionType type = mapper.getTypeFactory().constructCollectionType(List.class, DeptEntity.class);     // 反序列化     List<DeptEntity> target = mapper.readValue(json, type);     System.out.println(target); } 

Map 集合转换

@Test void test() throws JsonProcessingException {     // 构建List集合     Map<String, String> source = MapUtil.newHashMap();     source.put("aaa", "哈哈");     source.put("bbb", "呵呵");     // 序列化     String json = mapper.writeValueAsString(source);     // 构建Type对象     MapLikeType type = mapper.getTypeFactory().constructMapLikeType(HashMap.class, String.class, String.class);     // 反序列化     Map<String, String> target = mapper.readValue(json, type);     System.out.println(target); } 

复杂类型转换

这个部分的功能掌握了,类型转换就基本没啥问题了

带有泛型的转换

@Test void test() throws JsonProcessingException {     // 实体类     Result<DeptEntity> source = Result.success(new DeptEntity(10001, "部门A"));     // 序列化     String json = mapper.writeValueAsString(source);     // 构建Type对象     JavaType type = mapper.getTypeFactory().constructParametricType(Result.class, DeptEntity.class);     // 反序列化     Result<DeptEntity> target = mapper.readValue(json, type);     System.out.println(target.getData().getClass());     System.out.println(target); } 

泛型嵌套的转换

@Test void test() throws JsonProcessingException {     String key = "res";     // 重头戏来了 泛型嵌套的List集合     List<Map<String, Result<DeptEntity>>> source = CollUtil.newArrayList();     Map<String, Result<DeptEntity>> map = MapUtil.newHashMap();     Result<DeptEntity> res = Result.success(new DeptEntity(10001, "部门A"));     map.put(key, res);     source.add(map);     // 序列化     String json = mapper.writeValueAsString(source);     // 构建Type对象     SimpleType stringType = SimpleType.constructUnsafe(String.class);     JavaType result = mapper.getTypeFactory().constructParametricType(Result.class, DeptEntity.class);     MapLikeType mapType = mapper.getTypeFactory().constructMapLikeType(HashMap.class, stringType, result);     CollectionType type = mapper.getTypeFactory().constructCollectionType(List.class, mapType);     // 反序列化     List<Map<String, Result<DeptEntity>>> target = mapper.readValue(json, type);     System.out.println(target.get(0).get(key).getData().getClass());     System.out.println(target.get(0).get(key).getClass());     System.out.println(target.get(0).getClass());     System.out.println(target.getClass());     System.out.println(target); } 

Jackson 的配置项

常见的用法是把 Controller 回传给前端的 JSON 进行一些处理,例如时间格式化、忽略 NULL 值等等

这些配置可以在配置文件中完成,可以重新注入ObjectMapper,也可以使用实体类注解单独配置

这部分内容用到哪些配置项,想起来就补充,随缘更新

配置文件

spring:   jackson:     # 格式化日期时使用的时区     time-zone: GMT+8     # 格式化     date-format: yyyy-MM-dd HH:mm:ss.SSS     # 用于格式化的语言环境     locale: zh_CN     serialization:       # 是否开启格式化输出       indent_output: false 

重新注入 ObjectMapper

@Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {     // 通过该方法对mapper对象进行设置,所有序列化的对象都将该规则进行序列化     ObjectMapper objectMapper = builder.createXmlMapper(false).build();     // Include.Include.ALWAYS 默认     // Include.NON_DEFAULT 属性为默认值不序列化     // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量     // Include.NON_NULL 属性为NULL 不序列化     objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);     objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);     return objectMapper; } 

实体类注解

注解 作用
@JsonIgnoreProperties 批量设置转 JSON 时忽略的属性
@JsonIgnore 转 JSON 时忽略当前属性
@JsonProperty 修改转换后的 JSON 的属性名
@JsonFormat 转 JSON 时格式化属性的值
发表评论

评论已关闭。

相关文章