专栏首页技术趋势jsonPath-快速获取/设置json指定位置

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

背景

在一些特殊场景中,可能 一串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坐标

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.7.0</version>
</dependency>

Java操作示例

{
  "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。

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));

结果

[["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]]

实际场景

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

{
   
    "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":""
                }
            
            ] }
    ]
}
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);

结果

{
   
    "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 删除。
登录 后参与评论
0 条评论

相关文章

  • kettle的输入组件

    2、CSV文件是一种带有固定格式的文本文件。注意:获取字段的时候可以调整自己的字段类型,格式,满足自己的需求哦。

    别先生
  • 还在用 map[string]interface{} 处理 JSON?告诉你一个更高效的方法——jsonvalue

    本文介绍的是 jsonvalue 库,这是我个人在 Github 上开发的第一个功能比较多而全的 Go 库。目前主要是在腾讯未来社区的开发中使用,用于取代map...

    amc
  • Python快速入门

    最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大。很多身边的哥们也提到Python非常的简洁方便,比如用...

    用户1216676
  • Android开发笔记(六十二)HTTP数据格式的解析

    android有两种主流的json解析方案,一种是sdk自带的由Google提供的json(包名前缀为org.json),另一种是Alibaba提供的第三方...

    用户4464237
  • 有哪些你不知道的python小工具

    python作为越来越流行的一种编程语言,不仅仅是因为它语言简单,有许多现成的包可以直接调用。

    py3study
  • notepad++

    Notepad++是什么?为何推荐Notepad++?这些问题都不是这篇博文要回答的问题。但熟练掌握notepad++的使用技巧,无疑会大大提升专业技能。

    狼啸风云
  • Lottie动画原理

    导语:Lottie动画是Airbnb开源的一个支持 Android、iOS 以及 ReactNative。通过AE导出的JSON文件+Lottie库可快速实现动...

    QQ音乐技术团队
  • Go 每日一库之 jj

    在前面两篇文章中,我们分别介绍了快速读取 JSON 值的库gjson和快速设置 JSON 值的库sjson。今天我们介绍它们的作者tidwall的一个基于gjs...

    用户7731323
  • 上手玩一下 json-server(一)了解篇

    既然是造数据,就需要创建一个json数据。 在任意一个文件夹下(此处假设我创建了一个myserver文件夹),进入到该文件夹里面,执行代码:

    celineWong7
  • Web前端-Ajax基础技术(上)

    ajax是浏览器提供一套的api,用于向服务器发出请求,接受服务端返回的响应,通过javascript调用,实现通过代码控制请求与响应,实现网络编程。

    达达前端
  • day54_BOS项目_06

    第一步:根据提供的 业务受理.pdm 文件生成建表文件 bos_qp.sql 第二步:由于业务受理.pdm 文件中有伪表,所以我们需要修改生成的建表文件,修改如...

    黑泽君
  • 微博位置爬虫发布

    这个位置爬虫的结果可以和用户信息爬虫联动,比如有这样一个分析任务:去北京环球影城的人,都发了什么微博,男生多还是女生多,年龄群体分布怎么样,等等。都可以先用这个...

    月小水长
  • JS基础知识点(二)

    在上一篇文章《JS基础知识点(一)》中我们学习了什么是js、js写法、js数据类型、js的函数。在本篇文章中我们将学习重要的部分:面向对象以及常用对象(math...

    凯哥Java
  • 基于 HTML5 WebGL 的 3D SCADA 主站系统

    HT_hightopo
  • 基于Python操作将数据存储到本地文件

    前面说过Python爬取的数据可以存储到文件、关系型数据库、非关系型数据库。前面两篇文章没看的,可快速戳这里查看!《使用Python将数据存入SQLite3数据...

    JiekeXu之路
  • Kubernetes之kubectl命令行工具简介、安装配置及常用命令

    kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。运行kubectl命令的...

    菲宇
  • 基于 WebGL 的 HTML5 3D SCADA 主站系统 顶

    这个例子的初衷是模拟服务器与客户端的通信,我把整个需求简化变成了今天的这个例子。3D 的模拟一般需要鹰眼来辅助的,这样找产品以及整个空间的概括会比较明确,在这个...

    HT_hightopo
  • php 笔记 原

    (adsbygoogle = window.adsbygoogle || []).push({});

    tianyawhl
  • 用Python实现手机实时监控电脑资源

    有时候我们想查看电脑进程列表,实时掌握电脑或服务器资源消耗情况,或某指定应用资源消耗情况,最快速的方法就是通过Web框架开发部署可访问的网站。

    用户8949263

扫码关注腾讯云开发者

领取腾讯云代金券