Python json 处理之jsonpath、jsonpath-rw、jsonpath-rw-ext

一、jsonpath

1.1 jsonpath 介绍

jsonpath 是一种简单的方法来提取给定 json 文档的部分内容。 JsonPath有许多编程语言,如Javascript,Python和PHP,Java。

jsonpath 提供的 json 解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的 json 内容。

官方文档:https://goessner.net/articles/JsonPath/

在线 jsonpath 测试:http://www.e123456.com/aaaphp/online/jsonpath/

1.2 jsonpath 语法

和 XPath 表达式处理 XML 文档一样,jsonpath 用来处理 json 结构的数据。由于 json 结构通常是匿名的,而且不一定有“根成员对象”,因此 jsonpath 假定抽象名称 $ 分配给外层对象。

注:jsonpath 返回一个列表,若无匹配则返回 False

示例 json:

book_info = { "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
    }
  }
}
常用语法 说明 示例
$ 获取根元素,{}  
. 或 [] 获取子节点 $.store 或 $[store]
.. 深层扫描,可以查找任意层次的字段 $..book 或 $..author 
* 通配符,[*] 表示任何数据索引 $..book[*] 
[field,field2...] 根据字段或索引获取一组数据

$.store.book[0,1,2]     或     $.store.bicycle[color,price]

注:, 之后不能有空格 

[start:end:step] 数组切片  $..book[0:2] 
[?(express)] jsonpath 表达式  $..book[?(@.price==8.99)]

1.3 jsonpath 表达式

JsonPath 表达式是 JsonPath 最强大的功能之一,支持过滤运算符和函数。
格式:[?(expression)]

  • ? :标记表达式的开头
  • @ :表示当前节点,如 $..book[?(@.price < 10)]

注:jsonpath 表达式中目前只支持单引号

1.3.1 过滤器运算符

过滤器是用于筛选数组的逻辑表达式,可以使用逻辑运算符 && 和 || 创建更复杂的过滤器。字符串文字必须用单引号或双引号括起来([?(@.color == 'red')] 或者 [?(@.color == "red")]).

示例:典型的过滤器将是[?(@.price > 18)],其中@表示正在处理的当前项目。 

语法 说明 示例
== 等于 $..book[?(@.price==8.99)]
!= 不等于 $..book[?(@.price!=8.99)]
< 小于 $..book[?(@.price<8.99)]
<= 小于等于 $..book[?(@.price<=8.99)]
> 大于 $..book[?(@.price>19.95)]
>= 大于等于 $..book[?(@.price>=19.95)]
&& $..book[?(@.price==8.95 && @.category=='reference')]
|| $..book[?(@.price==8.95 || @.price==8.99)]

#
https://goessner.net/articles/JsonPath/ from jsonpath import jsonpath print(jsonpath(book_info, "$.store.bicycle[color,price]")) print(jsonpath(book_info, "$..book[0:2]")) print(jsonpath(book_info, "$..book[?(@.price<=8.99)]"))

二、jsonpath-rw

参考文档:https://jsonpath-rw.readthedocs.io/en/latest/#

jsonpath-rw 库支持稳定的 jsonpath 语法并附加了一些其他特性用来在 python 中解析 json 对象。

2.1 安装

pip install jsonpath-rw

2.2 示例

# 根节点 $
jsonpath_expr = parse('$')
print([match.value for match in jsonpath_expr.find(book_info)])

# 当前元素 `this`
jsonpath_expr = parse('$..color.`this`')    # ['red']
print([match.value for match in jsonpath_expr.find(book_info)])

# 父元素   `parent`
jsonpath_expr = parse('$..color.`parent`')  # [{'color': 'red', 'price': 19.95}]
print([match.value for match in jsonpath_expr.find(book_info)])

# 子代 .
jsonpath_expr = parse('$.store.bicycle')    # [{'color': 'red', 'price': 19.95}]
print([match.value for match in jsonpath_expr.find(book_info)])

# 子孙后代 ..
jsonpath_expr = parse('$.store..price') # [8.95, 12.99, 8.99, 22.99, 19.95]
print([match.value for match in jsonpath_expr.find(book_info)])

# expr1 where expr2,其中 expr2 是 expr1 的子节点
jsonpath_expr = parse('$..bicycle where price')   # [19.95]
print([match.value for match in jsonpath_expr.find(book_info)])

# 通配符
jsonpath_expr = parse('$..bicycle[*]')      # [{'color': 'red', 'price': 19.95}]
print([match.value for match in jsonpath_expr.find(book_info)])
jsonpath_expr = parse('$.store.*.price')    # [19.95]
print([match.value for match in jsonpath_expr.find(book_info)])

# 索引
jsonpath_expr = parse('$..book[2]') # [{'category': 'fiction', 'author': 'Herman Melville', 'title': 'Moby Dick', 'isbn': '0-553-21311-3', 'price': 8.99}]
print([match.value for match in jsonpath_expr.find(book_info)])

# 切片
jsonpath_expr = parse('$..book[1:3]')
print([match.value for match in jsonpath_expr.find(book_info)])

# 也可以直接使用函数构建表达式
# 等同于 store.book[1:2]
jsonpath_expr_direct = Fields('store').child(Fields('book')).child(Slice(1,2))
print(jsonpath_expr_direct)
print([match.value for match in jsonpath_expr_direct.find(book_info)])

三、jsonpath-rw-ext

jsonpath-rw-ext 对 jsonpath-rw 进行了一些拓展

官网:https://pypi.org/project/jsonpath-rw-ext/

import jsonpath_rw_ext as jp

# 根节点 $
print(jp.match('$', book_info)[0])
# $. 可省略
print(jp.match('store.bicycle', book_info)[0])
# 当前元素 `this`
print(jp.match('$..color.`this`', book_info)[0])  # res
# 父元素 `parent`
print(jp.match('$..color.`parent`', book_info)[0])  # {'color': 'red', 'price': 19.95}
# 通配符
print(jp.match('$..bicycle[*]', book_info)[0])  # {'color': 'red', 'price': 19.95}
# 索引
print(jp.match('$..book[2]', book_info)[0])  # {'category': 'fiction', 'author': 'Herman Melville', 'title': 'Moby Dick', 'isbn': '0-553-21311-3', 'price': 8.99}

# 长度 `len`
print(jp.match('$..book.`len`', book_info)[0])    # 4
# 排序
print(jp.match('$..bicycle.`sorted`[1]', book_info)[0])   # price
# 过滤,()可省略
print(jp.match('$..book[?(@.price<10)]', book_info))
print(jp.match('$..book[?@.price<10]', book_info))
# 正则过滤
print(jp.match('$..book[?@.author ~ ".*?Melville"].price', book_info))
# 过滤指定字段
print(jp.match('$..book[0].(category|title)', book_info))

 

posted @ 2020-11-02 14:04  芒果日记  阅读(1745)  评论(0)    收藏  举报