大数跨境
0
0

Spring Boot玩转JSON!解锁Jackson的8大高阶技能,太强了

Spring Boot玩转JSON!解锁Jackson的8大高阶技能,太强了 Spring全家桶实战案例
2025-11-02
2
导读:Spring Boot玩转JSON!解锁Jackson的8大高阶技能,太强了
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新186个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

本篇文章将介绍使用Jackson库处理JSON数据的多种高级技术,涵盖了JSON解析、查询、序列化/反序列化控制等核心功能。主要实现了以下能力:

  • JSON路径查询:通过findValue()at()方法实现嵌套JSON结构的深度查询

  • 多值提取:支持批量获取相同名称的多个值

  • 视图控制:使用@JsonView实现字段级序列化控制,区分公开和内部视图

  • 动态属性处理:通过@JsonAnySetter/Getter处理未知字段,实现灵活的动态对象

  • 对象展开:使用@JsonUnwrapped将嵌套对象属性扁平化到父级

  • 原始JSON保留:通过@JsonRawValue保持字符串字段的原始JSON格式

这些功能组合构成了强大的JSON数据处理能力,适用于API开发、配置解析、数据转换等场景,特别适合需要灵活处理复杂JSON结构的Java应用程序。

2.实战案例

2.1 findValue查找值

Jackson中的findValue()方法允许我们在JSON树中搜索特定键值并获取其关联的值。首先,我们将使用ObjectMapper将JSON字符串转换为JsonNode,从而创建JSON数据的树形表示:

@Testpublic void test1() throws Exception {  String json = """      {        "user": {          "id": 1,          "name": "Pack_xg",          "details": {            "email": "pack@gmail.com",            "phone": "18999999999"          }        }      }      """ ;  ObjectMapper mapper = new ObjectMapper();  JsonNode rootNode = mapper.readTree(json) ;
  String email = rootNode.findValue("email").asText();  System.err.println(email) ;}

输出结果

pack@gmail.com

2.2 优雅处理缺失的键

在处理 JSON 时,我们可能会遇到键值缺失的情况。当 JSON 结构中找不到指定键时,findValue() 方法将返回 null。如下示例:

@Testpublic void test2() throws Exception {  String json = """      {        "user": {          "id": 1,          "name": "Pack_xg",          "details": {            "phone": "18999999999"          }        }      }      """ ;  ObjectMapper mapper = new ObjectMapper();  JsonNode rootNode = mapper.readTree(json);  JsonNode emailNode = rootNode.findValue("email");  System.err.println(emailNode) ;}

输出结果

null

在此示例中,findValue("email") 返回 null,因为 JSON 中不存在 email 键。

2.3 使用 findValues() 方法处理数组

findValues方法查找指定名称的JSON对象字段的方法——包括直接子值和后代值——并将找到的字段作为List返回。

@Testpublic void test3() throws Exception {  String json = """        {          "users": [            { "id": 1, "name": "pack", "details": { "email": "pack@gmail.com" } },            { "id": 2, "name": "xg", "details": { "email": "xg@qq.com" } }          ]        }      """;  ObjectMapper mapper = new ObjectMapper();  JsonNode rootNode = mapper.readTree(json);  List<String> emails = rootNode.findValues("email")      .stream()      .map(JsonNode::asText)      .toList() ;  System.err.println(emails) ;}

输出结果

[pack@gmail.com, xg@qq.com]

2.4 处理深度嵌套的key

与其在JSON结构中通过名称查找键值,我们可使用at()方法定位深层嵌套JSON结构中特定路径下的字段。如下示例:

@Testpublic void test4() throws Exception {  String json = """      {        "company": {          "dept": {            "team": {              "lead": {                "name": "Pack_xg",                "details": {                  "email": "pack@gmail.com"                }              }            }          }        }      }      """ ;
  ObjectMapper mapper = new ObjectMapper();  JsonNode rootNode = mapper.readTree(json);  String email = rootNode.at("/company/dept/team/lead/details/email").asText() ;  System.err.println(email) ;}

输出结果

pack@gmail.com

此处传递给 at() 方法的路径是一个 JSON 指针,它是一种使用字符串语法遍历 JSON 文档的标准化方式

2.5 使用@JsonView视图控制字段输出

用于指示由被注解的方法或字段所定义的属性所属视图(一个或多个)的注解。示例注解如下:

@JsonView(BasicView.class)

该注解指定,被注解的属性在处理(序列化、反序列化)由BasicView.class(或其子类)标识的视图时将被包含。如果包含多个视图类标识符,则该属性将属于所有这些视图。

public class User {  public interface PublicView {}  public interface InternalView extends PublicView {}  @JsonView(PublicView.class)  private String name;  @JsonView(InternalView.class)  private String email;  @JsonView(InternalView.class)  private String password;}

测试用例

@Testpublic void test5() throws Exception {  User user = new User("Pack_xg""pack@gmail.com""123456") ;  // 使用  ObjectMapper mapper = new ObjectMapper();  // 只输出 public 字段  String publicJson = mapper      .writerWithView(User.PublicView.class)      .writeValueAsString(user);  System.err.println(publicJson) ;  // 输出所有字段  String internalJson = mapper      .writerWithView(User.InternalView.class)      .writeValueAsString(user);  System.err.println(internalJson) ;}

输出结果

{"name":"Pack_xg"}{"name":"Pack_xg","email":"pack@gmail.com","password":"123456"}

关于@JsonView更多用法,请查看下面链接:

绝了!Spring Boot凭@JsonView注解,强大到逆天

2.6 处理未知属性

@JsonAnySetter / @JsonAnyGetter 用于处理 JSON 中可能存在的额外字段,避免反序列化失败。如下示例:

public class DynamicObject {  private Long id ;  private String name ;  private Map<StringObject> properties = new HashMap<>();  // ...  @JsonAnySetter  public void set(String name, Object value) {    properties.put(name, value);  }  @JsonAnyGetter  public Map<StringObjectgetProperties() {    return properties;  }}

测试用例

@Testpublic void test6() throws Exception {  String json = """      {        "id": 666,        "name": "Pack_xg",        "age": 33,        "details": {          "phone": "18999999999",          "addr": "中国"        }      }      """;  ObjectMapper objectMapper = new ObjectMapper() ;  // 反序列化:未知字段会被 @JsonAnySetter 捕获  DynamicObject user = objectMapper.readValue(json, DynamicObject.class);  System.out.println(user);  // 序列化:properties 中的内容会被 @JsonAnyGetter 写回 JSON  String serializedJson = objectMapper.writeValueAsString(user);  System.out.println("\n重新序列化后的 JSON:");  System.out.println(serializedJson);}

输出结果

2.7 扁平化嵌套对象

将嵌套对象的字段“展开”到外层。

public class Order {  private Long id ;  private String orderNo ;  @JsonUnwrapped  private Address address ;}public class Address {  private String provice;  private String city ;  private String county ;}

测试用例

@Testpublic void test7() throws Exception {  Order order = new Order(1L"XP-00001"new Address("新疆""乌鲁木齐""天山区")) ;  ObjectMapper objectMapper = new ObjectMapper() ;  System.err.println(objectMapper.writeValueAsString(order)) ;}

输出结果

{  "id" : 1,  "orderNo" : "XP-00001",  "provice" : "新疆",  "city" : "乌鲁木齐",  "county" : "天山区"}

2.8 插入原始JSON

@JsonRawValue将一个字符串字段的内容直接作为原始 JSON 片段写入最终的 JSON 输出中,而不是将其转义为字符串。这在你需要嵌入已生成的 JSON 或动态 JSON 结构时非常有用。如下示例:

public class Product {  private String name ;  private BigDecimal price ;  /**json字符串内容*/  @JsonRawValue  private String details ;}

测试用例

@Testpublic void test7() throws Exception {  Order order = new Order(1L"XP-00001"new Address("新疆""乌鲁木齐""天山区")) ;  ObjectMapper objectMapper = new ObjectMapper() ;  objectMapper.enable(SerializationFeature.INDENT_OUTPUT) ;  System.err.println(objectMapper.writeValueAsString(order)) ;}

输出结果

{  "name" : "Spring Boot3实战案例200讲",  "price" : 70,  "details" : {"author": "pack_xg", "page_count": 1000}}

如果没有@JsonRawValue注解,输出结果如下:

{  "name" : "Spring Boot3实战案例200讲",  "price" : 70,  "details" : "{\"author\"\"pack_xg\"\"page_count\": 1000}"}

字符串被转义了。



以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

系统设计30个核心技能,每一个开发者都必须掌握

Spring Boot 处理JSON的6大强悍功能

性能相差60倍!Spring Boot 批量插入你做对了吗?5种方式对比

高级开发!手撕Controller底层调用链,深度功能扩展、性能优化

开发必备!掌握Spring Boot开发最核心的12个功能

杜绝重复启动!Spring Boot 单实例运行4种方案

玩转MCP!Spring AI 3秒接入百度地图MCP服务

抛弃@Valid注解!Yavi用一行代码实现各种复杂验证

Spring Boot 请求处理超大JSON数据 3种 方式性能对比

知道太晚了!实时通信新选择fetch-event-source,真香

Spring AI + LangGraph4j 多智能体开发,太强大了!

告别OOM!Spring Boot 流式导出百万数据:支持MyBatis/JPA/Jdbc

图片
图片
图片
图片
图片
图片
图片
图片
图片

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读195
粉丝0
内容832