前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jsonPath-快速获取/设置json指定位置

jsonPath-快速获取/设置json指定位置

作者头像
逍遥壮士
发布2022-06-15 17:45:33
1.6K0
发布2022-06-15 17:45:33
举报
文章被收录于专栏:技术趋势技术趋势

背景

在一些特殊场景中,可能 一串json有几个甚至上万个节点,那么要去获取里面某一个节点或者说设置某个json指定key的值,那就非常麻烦了,一般我们是通过递归来进行获取,获取后还需要再通过递归进行遍历设置值,所以相当来说非常麻烦。是否有已有现成的工具进行设置呢?

注:使用当先请跳转到:注意点进行了解性能问题。

jsonPath介绍

官网:https://goessner.net/articles/JsonPath/

github官网:https://github.com/json-path/JsonPath

jsonPath是一个非常强大的,可以通过规则、指定的格式获取或设置需要的json位置,通过jsonPath可以快速实现json自定义的位置获取或赋值。

以下相关API说明,来源于github翻译后:

过滤器运算符

过滤器是用于筛选数组的逻辑表达式。一个典型的过滤器将是[?(@.age > 18)],其中@表示正在处理的当前项目。可以使用逻辑运算符&&和||创建更复杂的过滤器。字符串文字必须用单引号或双引号括起来([?(@.color == 'blue')] 或者 [?(@.color == "blue")]).

操作符

描述

==

left等于right(注意1不等于'1')

!=

不等于

<

小于

<=

小于等于

>

大于

>=

大于等于

=~

匹配正则表达式[?(@.name =~ /foo.*?/i)]

in

左边存在于右边 [?(@.size in ['S', 'M'])]

nin

左边不存在于右边

size

(数组或字符串)长度

empty

(数组或字符串)为空

jsonPath的使用

引入java的POM坐标

代码语言:javascript
复制
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.7.0</version>
</dependency>

Java操作示例

代码语言:javascript
复制
{
  "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
}

JsonPath (点击链接测试)

结果

$.store.book[*].author

获取json中store下book下的所有author值

$..author

获取所有json中所有author的值

$.store.*

所有的东西,书籍和自行车

$.store..price

获取json中store下所有price的值

$..book[2]

获取json中book数组的第3个值

$..book[-2]

倒数的第二本书

$..book[0,1]

前两本书

$..book[:2]

从索引0(包括)到索引2(排除)的所有图书

$..book[1:2]

从索引1(包括)到索引2(排除)的所有图书

$..book[-2:]

获取json中book数组的最后两个值

$..book[2:]

获取json中book数组的第3个到最后一个的区间值

$..book[?(@.isbn)]

获取json中book数组中包含isbn的所有值

$.store.book[?(@.price < 10)]

获取json中book数组中price<10的所有值

$..book[?(@.price <= $['expensive'])]

获取json中book数组中price<=expensive的所有值

$..book[?(@.author =~ /.*REES/i)]

获取json中book数组中的作者以REES结尾的所有值(REES不区分大小写)

$..*

逐层列出json中的所有值,层级由外到内

$..book.length()

获取json中book数组的长度

使用 JsonPath 最简单最直接的方法是通过静态读取 API。

代码语言:javascript
复制
String rule3 =  FileTool.readFileString("D:\\workspace\\jsonpath_study\\src\\main\\java\\com.hong.test\\demo.json","UTF-8");
        List<String> authors = JsonPath.read(rule3, "$.store.book[*].author");
        System.out.println(Arrays.asList(authors));

结果

代码语言:javascript
复制
[["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]]

实际场景

需要将下面的json,找到指定compType为http的节点,并且找到后,循环赋值到这个节点下面的chidren里面。比如

代码语言:javascript
复制
{
   
    "compName":"xxx",
    "identifyName":"order",
    "compCode":"001",
    "compType":"http",
    "parentCompType":"service",
    "parentCompCode":"",
    "compIndex":"1",
    "children":[
        {
            "compName":"版本",
            "compType":"httpVersionNumber",
            "compValue":"1.0",
            "parentCompType":"http",
            "compIndex":1,
            "children":[

            ],
            "currentPosition":""
        },
        {
            "compName":"服务x",
            "compType":"httpInstanceCode",
            "compValue":"xx",
            "parentCompType":"http",
            "compIndex":2,
            "children":[

            ],
            "currentPosition":""
        },
        {
            "compName":"xx列表",
            "compType":"httpRequest",
            "compValue":"",
            "parentCompType":"http",
            "compIndex":3,
            "children":[
                {
                    "compName":"用户名称",
                    "compType":"reqParams",
                    "compValue":"userName",
                    "parentCompType":"httpRequest",
                    "compIndex":1,
                    "children":[
                        {
                            "compName":"x",
                            "compType":"reqMapping",
                            "compValue":"order.userName",
                            "parentCompType":"reqParams",
                            "compIndex":1,
                            "children":[

                            ],
                            "currentPosition":""
                        }
                    ],
                    "currentPosition":""
                }
            
            ] }
    ]
}
代码语言:javascript
复制
String rule2 = FileTool.readFileString("D:\\workspace\\jsonpath_study\\src\\main\\java\\com.hong.test\\b.json", "UTF-8");
        JSONArray array = JSONObject.parseArray(JsonPath.read(rule2, "$..children[?(@.compType=='http')]").toString());
        int i = 0;
        while (i < 10000) {
            i++;
            for (Object o : array) {
                JSONObject json = (JSONObject) o;

                rule2 = JsonPath.parse(rule2).set("$..children[?(@.compCode=='" + json.get("compCode") + "')].children", "aa").jsonString();
            }
        }
        System.out.println(rule2);

结果

代码语言:javascript
复制
{
   
    "compName":"xxx",
    "identifyName":"order",
    "compCode":"001",
    "compType":"http",
    "parentCompType":"service",
    "parentCompCode":"",
    "compIndex":"1",
    "children":“aa”
}

可以看到快速替换了,很方便。

注意点

上面为什么要用1万次,就是测试jsonPath的性能问题,可以发现,jsonpath如果在多个执行中会导致CPU突然间飙升20%~50%,这一点是需要注意的,如果你的json或者线上的环境本来cpu使用率就很高那就要注意是否符合你的场景,但是我这个json是非常非常长的,有一百多kb,一般情况下是不可能有这么长,所以还是需要根据自已的实际场景进行判断是否引用。切记 切记 切记

最后

jsonPath底层也是通过递归的方式进行实现,有兴趣的同学可以进行研究底层源码。需要特别注意的是如果引用了jsonPath那么需要特别关注cpu的性能指标,jsonPath会在短时间内将执行的cpu突增20%~50%(大json),可能会导致cpu飙高,所以要特别注意是否适用当前场景。

阅读文档

参考地址:

https://zhuanlan.zhihu.com/p/30188199

http://www.ibloger.net/article/2329.html

https://www.leftso.com/blog/796.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • jsonPath介绍
    • 以下相关API说明,来源于github翻译后:
      • 过滤器运算符
      • jsonPath的使用
      • Java操作示例
      • 使用 JsonPath 最简单最直接的方法是通过静态读取 API。
    • 实际场景
      • 阅读文档
  • 注意点
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档