当前位置:   article > 正文

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

jsonpath设置值

背景

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

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

jsonPath介绍

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

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

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

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

bb62f2c7cfd060d404e1cc66d5c5d5d9.png

8a808bb30ec4767bb3451d6d07dbf785.png

过滤器运算符

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

操作符

描述

==

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

!=

不等于

<

小于

<=

小于等于

>

大于

>=

大于等于

=~

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

in

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

nin

左边不存在于右边

size

(数组或字符串)长度

empty

(数组或字符串)为空

jsonPath的使用

引入java的POM坐标

  1. <dependency>
  2. <groupId>com.jayway.jsonpath</groupId>
  3. <artifactId>json-path</artifactId>
  4. <version>2.7.0</version>
  5. </dependency>

Java操作示例

  1. {
  2. "store": {
  3. "book": [
  4. {
  5. "category": "reference",
  6. "author": "Nigel Rees",
  7. "title": "Sayings of the Century",
  8. "price": 8.95
  9. },
  10. {
  11. "category": "fiction",
  12. "author": "Evelyn Waugh",
  13. "title": "Sword of Honour",
  14. "price": 12.99
  15. },
  16. {
  17. "category": "fiction",
  18. "author": "Herman Melville",
  19. "title": "Moby Dick",
  20. "isbn": "0-553-21311-3",
  21. "price": 8.99
  22. },
  23. {
  24. "category": "fiction",
  25. "author": "J. R. R. Tolkien",
  26. "title": "The Lord of the Rings",
  27. "isbn": "0-395-19395-8",
  28. "price": 22.99
  29. }
  30. ],
  31. "bicycle": {
  32. "color": "red",
  33. "price": 19.95
  34. }
  35. },
  36. "expensive": 10
  37. }

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。

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

结果

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

实际场景

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

  1. {
  2.    
  3.     "compName":"xxx",
  4.     "identifyName":"order",
  5.     "compCode":"001",
  6.     "compType":"http",
  7.     "parentCompType":"service",
  8.     "parentCompCode":"",
  9.     "compIndex":"1",
  10.     "children":[
  11.         {
  12.             "compName":"版本",
  13.             "compType":"httpVersionNumber",
  14.             "compValue":"1.0",
  15.             "parentCompType":"http",
  16.             "compIndex":1,
  17.             "children":[
  18.             ],
  19.             "currentPosition":""
  20.         },
  21.         {
  22.             "compName":"服务x",
  23.             "compType":"httpInstanceCode",
  24.             "compValue":"xx",
  25.             "parentCompType":"http",
  26.             "compIndex":2,
  27.             "children":[
  28.             ],
  29.             "currentPosition":""
  30.         },
  31.         {
  32.             "compName":"xx列表",
  33.             "compType":"httpRequest",
  34.             "compValue":"",
  35.             "parentCompType":"http",
  36.             "compIndex":3,
  37.             "children":[
  38.                 {
  39.                     "compName":"用户名称",
  40.                     "compType":"reqParams",
  41.                     "compValue":"userName",
  42.                     "parentCompType":"httpRequest",
  43.                     "compIndex":1,
  44.                     "children":[
  45.                         {
  46.                             "compName":"x",
  47.                             "compType":"reqMapping",
  48.                             "compValue":"order.userName",
  49.                             "parentCompType":"reqParams",
  50.                             "compIndex":1,
  51.                             "children":[
  52.                             ],
  53.                             "currentPosition":""
  54.                         }
  55.                     ],
  56.                     "currentPosition":""
  57.                 }
  58.             
  59.             ] }
  60.     ]
  61. }
  1. String rule2 = FileTool.readFileString("D:\\workspace\\jsonpath_study\\src\\main\\java\\com.hong.test\\b.json", "UTF-8");
  2.         JSONArray array = JSONObject.parseArray(JsonPath.read(rule2, "$..children[?(@.compType=='http')]").toString());
  3.         int i = 0;
  4.         while (i < 10000) {
  5.             i++;
  6.             for (Object o : array) {
  7.                 JSONObject json = (JSONObject) o;
  8.                 rule2 = JsonPath.parse(rule2).set("$..children[?(@.compCode=='" + json.get("compCode") + "')].children", "aa").jsonString();
  9.             }
  10.         }
  11.         System.out.println(rule2);

结果

  1. {
  2.    
  3.     "compName":"xxx",
  4.     "identifyName":"order",
  5.     "compCode":"001",
  6.     "compType":"http",
  7.     "parentCompType":"service",
  8.     "parentCompCode":"",
  9.     "compIndex":"1",
  10.     "children":“aa”
  11. }

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

注意点

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

d0f9995f8e70290e4b554f206de30e51.png

最后

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

9d3771b0c4fab91957fc4d2f674ae743.png

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/977884
推荐阅读
相关标签
  

闽ICP备14008679号