Springboot JSON 转换:Jackson篇

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

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


    org.springframework.boot
    spring-boot-starter-web

    org.springframework.boot
    spring-boot-starter-test

    org.projectlombok
    lombok

    cn.hutool
    hutool-all
    5.8.3

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

@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 {

    private int code;
    private String msg;
    private T data;

    public static  Result 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");
    // 序列化 writerWithDefaultPrettyPrinter 的作用是美化JSON
    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);
    // 序列化 writerWithDefaultPrettyPrinter 的作用是美化JSON
    String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
    // 反序列化
    System.out.println(mapper.readValue(json, UserEntity.class));
}

集合相比基础类型多个泛型的概念,需要构建类型对象进行转换,简单了解这两种集合就够了,复杂一点的后面会提到

Collection 集合转换

@Test
void test() throws JsonProcessingException {
    // 构建List集合
    List source = CollUtil.newArrayList();
    for (int i = 1; i  target = mapper.readValue(json, type);
    System.out.println(target);
}

Map 集合转换

@Test
void test() throws JsonProcessingException {
    // 构建List集合
    Map 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 target = mapper.readValue(json, type);
    System.out.println(target);
}

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

带有泛型的转换

@Test
void test() throws JsonProcessingException {
    // 实体类
    Result source = Result.success(new DeptEntity(10001, "部门A"));
    // 序列化
    String json = mapper.writeValueAsString(source);
    // 构建Type对象
    JavaType type = mapper.getTypeFactory().constructParametricType(Result.class, DeptEntity.class);
    // 反序列化
    Result 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>> source = CollUtil.newArrayList();
    Map> map = MapUtil.newHashMap();
    Result 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>> 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);
}

常见的用法是把 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 时格式化属性的值

Original: https://www.cnblogs.com/hanzhe/p/16814285.html
Author: Java小学生丶
Title: Springboot JSON 转换:Jackson篇

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/800409/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球