Java - JsonPath 特殊场景解决方案

我们先看下JSONPath的使用,这里使用的是 GitHub - json-path/JsonPath: Java JsonPath implementation,其README中已经提供了相关的介绍和使用示例,这里再简单介绍下,我们这里直接使用其中的示例数据。

{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  },
  "expensive": 10
}
  1. JSONPath的表达式都是以 $ 开始,表示根节点

  2. 属性值获取:子节点可以使用 .<name> 来进行表示,如: $.store.bicycle.color 或者 $['store']['bicycle']['color']可以获取其中的color值

  3. 获取多个属性值:JSONPath表达式最后一级子节点可以同时获取多个值,如 $['store']['bicycle']['color', 'price']

  4. 数组数据获取:可以根据索引获取指定位置元素,如: $.store.book[0,1] 或者 $.store.book[:2] 或者 $.store.book[-1]

  5. 可以使用通配符*进行匹配,如:$.store.book[*] 或者 $.store.bicycle.*

  6. 深度查找可以使用..<name>来对属性进行查找,而不管它的具体位置,如:$..price

  7. 属性/数组过滤可以使用[?(<expression>)],其中的表达式需要能解析为boolean值,如:$.store.bicycle[?(@.color=='red')] 或者 $.store.book[?(@.price < 10)]

  8. 函数使用:可以使用lengh()等函数,如:$.store.book.length() 、$.numbers.sum()

  • 相关API用法如下
final JsonPath compile = JsonPath.compile("$.store.book[0].author");
String json = "...";
final String author = compile.read(json);

// 或者如果不重复使用的话,可以直接写成一步
List<String> authors = JsonPath.read(json, "$.store.book[*].author");

// 函数使用(需要注意函数能作用的数据类型,如 min(), max(), sum()等只能作用于数值数组)
String json = "{\"numbers\":[1,3,4,7,-1]}";
final Object read = JsonPath.read(json, "$.numbers.sum()"); // 输出:14.0
  • 除此之外,JsonPath还提供了一些额外的配置项,以仓库中的 json 为例子
[
   {
      "name" : "john",
      "gender" : "male"
   },
   {
      "name" : "ben"
   }
]
  • DEFAULT_PATH_LEAF_TO_NULL

叶子节点找不到时默认为null: 正常情况下通过Path找不到数据值,JsonPath会抛出异常(使用了通配符如[*]等除外,这种找不到路径是会返回空集合),增加此配置后在叶子结点找不到数据时会返回null 而不是异常(仅限叶子结点,中间节点不存在时仍然会抛出异常)

Configuration configuration =    Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL).build();
Object data = JsonPath.using(configuration).parse(json).read("$[1]['gender']");

// data == null
  • ALWAYS_RETURN_LIST

不管JsonPath获取的结果是单个值还是集合,都会包装成集合返回

Configuration configuration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.ALWAYS_RETURN_LIST).build();
Object data = JsonPath.using(configuration).parse(json).read("$[*]['gender']");

// data == ["male",null]

// 如果默认使用的话,默认会数组对象key不存在的话会错位上去,所以业务中如果同时有需求的话,生成 2 个 DocumentContext 去操作比较好
Object data = JsonPath.parse(json).read("$[*]['gender']");
  • SUPPRESS_EXCEPTIONS

当处理发生异常时,如果配置了 ALWAYS_RETURN_LIST,则返回空集合,否则返回 null

Configuration configuration = Configuration.builder().options(Option.ALWAYS_RETURN_LIST, Option.SUPPRESS_EXCEPTIONS).build();
Object data = JsonPath.using(configuration).parse(json).read("$[0]['abc']['def']");

// data = []
  • REQUIRE_PROPERTIES

路径中属性不存在时,会抛出异常,因为本身路径不存在就会抛出异常,所以这个配置主要体现在配置通配符的场景下,且如果同时配置了 SUPPRESS_EXCEPTIONS, 则 SUPPRESS_EXCEPTIONS 优先(不会抛出异常)

Configuration configuration = Configuration.builder().options(Option.ALWAYS_RETURN_LIST).build();
Object data = JsonPath.using(configuration).parse(json).read("$[*]['gender']");

// 抛出异常
  • 值替换

以上主要是读取的操作,同时它还支持对数据进行修改,调用对应的 set 方法即可

String newJson = JsonPath.parse(json).set("$['store']['book'][0]['author']", "Paul").jsonString();
### Java 使用 JSONPath 提取 Token 为了在Java中使用JSONPath来提取Token,首先需要引入必要的Maven依赖项。这可以通过编辑`pom.xml`文件并加入如下所示的依赖项完成[^4]: ```xml <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.6.0</version> </dependency> ``` 一旦设置了项目环境,就可以编写一段简单的程序来解析含有Token信息的JSON字符串,并利用JSONPath表达式从中抽取所需的Token值。 下面是一个具体的例子,展示了如何定义一个方法来进行此操作: ```java import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; public class ExtractTokenExample { public static String extractToken(String jsonString, String jsonPathExpression) { try { Object obj = new JSONParser(JSONParser.MODE_JSON_SIMPLE).parse(jsonString); JSONObject jsonObject = (JSONObject) obj; DocumentContext context = JsonPath.parse(jsonObject); List<String> tokens = context.read(jsonPathExpression); if (!tokens.isEmpty()) { return tokens.get(0); // 假设只需要第一个匹配的结果作为token返回 } } catch (Exception e) { System.out.println("Error parsing or extracting from the provided JSON string."); e.printStackTrace(); } return null; // 如果未找到任何token,则返回null } public static void main(String[] args) { // 示例JSON字符串 String sampleJson = "{ \"data\": {\"access_token\":\"example-token-value\",\"expires_in\":3600}}"; // 定义要查询的路径 String pathToToken = "$.data.access_token"; // 调用函数获取token String extractedToken = extractToken(sampleJson, pathToToken); // 输出结果 System.out.println("Extracted Access Token: " + extractedToken); } } ``` 这段代码实现了从给定的JSON格式字符串中按照指定的JSONPath表达式检索出对应的Token值的功能。这里假设输入的是一个标准形式的OAuth响应体样式的JSON串,其中包含了名为`access_token`字段作为目标Token的位置[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆克和他的代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值