首页 > 编程语言 >Jayway JsonPath-提取JSON文档内容的Java DSL | 京东物流技术团队

Jayway JsonPath-提取JSON文档内容的Java DSL | 京东物流技术团队

时间:2023-11-27 11:03:16浏览次数:34  
标签:Java price 元素 Jayway DSL JsonPath 数组 匹配 odOrderDetailList

介绍

JsonPath是一种能够提取部分JSON文档属性、对象、数组的语法,支持条件过滤、数学运算、字符串处理等功能。JsonPath与JSON文档就像 XPath 表达式与 XML 文档结合使用一样。

由于 JSON 结构通常是匿名的,并不一定和XML一样具有“根成员对象”,因此 JsonPath假定分配$给外层对象的抽象名称。JsonPath由用点分隔的表达式段(操作符)组成。 操作符可以是一个简单的词,如 JSON 值名称、*,也可以是括在方括号 \[ \] 中的更复杂的构造。 括号段前的分隔点是可选的,也可以省略。下面是几种JsonPath的提取JSON文档内容语法:

JsonPath

描述

$.object.name

返回object.name的内容。

$.object\['name'\]

返回object.name的内容。

$.object.\['name'\]

返回object.name的内容。

$.object.history.length()

返回object.history数组元素的个数。

$\[?(@.name == 'Object')\].price.first()

返回第一个名为'Object'的对象的价格字段。

$\[?(@.price > 10)\].length()

返回price大于10的对象个数。

Jayway JsonPathStefan Goessner JsonPath的Java实现,是用于读取JSON文档的Java DSL。本文主要通过Jayway JsonPath来简单介绍JsonPath的使用语法,通过真实报文案例来进行操作。

支持的操作符

操作符

描述

$

查询的根节点对象,表示一个json的数据,可以是对象或数组

@

当前节点对象

*

通配符,获取所有节点

..

递归查找,查找所有层次的属性值

<name>

按名称匹配对象属性。

.<name>

按照名称查找子节点

['<name>','<name>',...]

可用查找多个节点

[<number>,<number>,...]

按索引匹配数组元素,可同时查找多个数组元素

[start:end]

按定义的范围匹配数组元素:

<start>\- 要匹配的第一个索引(包括)。 如果未指定,则匹配从头开始的所有数组元素。 如果为负数,则指定从数组末尾开始的偏移量。
<end>\- 要匹配的最后一个索引(不包括)。 如果未指定,则匹配所有数组元素到最后。 如果为负数,则指定从数组末尾开始的偏移量。 | | [?(<expression>)] | 过滤表达式可匹配对象/数组元素,表达式的结果必须为布尔值 |

可以通过在 JSONPath 中添加 ~ 后缀来提取匹配的元素名称。 它返回匹配对象的名称或匹配数组项的字符串格式的索引。

过滤操作符

操作符

描述

==

等于

!=

不等于

<

小于

<=

小于或等于

>

大于

>=

大于或等于

=~

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

in

包含 \[?(@.size in \['S', 'M'\])\]

nin

不包含

subsetof

子集 \[?(@.sizes subsetof \['S', 'M', 'L'\])\]

anyof

交集 \[?(@.sizes anyof \['M', 'L'\])\]

noneof

不是交集 \[?(@.sizes noneof \['M', 'L'\])\]

size

左侧(数组或字符串)的大小应与右侧匹配

empty

左侧(数组或字符串)应该为空

支持的函数

可以在JsonPath表达式执行后进行调用,其输入值为表达式的结果。函数的输出看具体某个函数的含义。

函数

描述

返回值类型

min()

数值类型数组最小值

Double

max()

数值类型数组最大值

Double

avg()

数值类型数组平均值

Double

stddev()

数值类型数组标准差

Double

length()

数组长度

Integer

sum()

数值类型数组求和

Double

keys()

提取匹配的元素名称与~操作符功能一致

Set<E>

concat(X)

拼接

与入参相同

append(X)

把元素添加到JsonPath输出的数组中

与入参相同

first()

数组中的第一个元素

数组中元素类型

last()

数组中的最后一个元素

数组中元素类型

index(X)

提供索引为X的数组的元素,如果X为负数,则从后往前取

数组中元素类型

用一个复杂的接单报文来演示

https://jsonpath.com,这个在线网站可以用来验证JsonPath表达式,但是不支持函数,函数可以通过java代码来验证。

String json ="{.....}";
Object read = JsonPath.read(json, "$..price.min()");
System.out.println(read);

示例报文

{
    "address":"大良街道同兴路****",
    "createTime":"2023-09-20 17:48:44",
    "customerName":"培^_^",
    "id":0,
    "memberId":"ECP002000*****",
    "mobile":"184^_^8547",
    "extendMessage":{
        "clientNo":"testEBU516154",
        "clientName":"广州网络科技有限公司",
        "spSoNo":"test1976065878296",
        "road":"011"
    },
    "odOrderDetailList":[
        {
            "id":1,
            "productName":"白医生中频针灸理疗仪家用医院医用多功能颈椎肩周炎腰肌劳损电疗经络激光低频按摩器同款中频激光综合治疗仪 2023新款",
            "quantity":1,
            "productSku":"38fjjjj",
            "price":189.6
        },
        {
            "id":2,
            "productName":"测试SKU",
            "quantity":3,
            "productSku":"ESG03JJ1",
            "price":200
        }
    ],
    "totalPrice":0,
    "volume":17318.4,
    "extendInfo":{
        "templateInfo":[
            {
                "code":"TP123",
                "isPrint":1,
                "type":2,
                "printType":0
            },
            {
                "code":"TPABC",
                "isPrint":1,
                "type":4,
                "printType":0
            }
        ],
        "attrs":{
            "plateFormCode":"274"
        },
        "senderName":"流苏",
        "senderAddress":"广东省中山市南头镇永辉北路*****",
        "paymentTime":"2023-09-20 17:22:31"
    },
    "carrierName":"京东配送",
    "provinceName":"广东",
    "isConsumable":0,
    "merchantType":"0",
    "tags":[
        "a",
        "b",
        "c",
        "d",
        "e"
    ]
}

操作结果

JsonPath

结果

$.extendMessage.clientName

"广州网络科技有限公司"

$.extendMessage\['clientNo'\]

"testEBU516154"

$.extendMessage

{"clientNo":"testEBU516154","clientName":"广州网络科技有限公司","spSoNo":"test1976065878296","road":"011"}

$.odOrderDetailList\[0\].productName

"白医生中频针灸理疗仪家用医院医用多功能颈椎肩周炎腰肌劳损电疗经络激光低频按摩器同款中频激光综合治疗仪 2023新款"

$.odOrderDetailList\[-1\].productName

"测试SKU"

$.odOrderDetailList.length()

2

$.tags\[:\]

\["a", "b", "c", "d", "e" \]

$.tags\[2:\]

\["c", "d", "e" \]

$.tags\[:3\]

\["a", "b", "c"\]

$.tags\[1:4\]

\["b", "c", "d"\]

$.tags\[-2:\]

\["d", "e"\]

$.tags\[:-3\]

\["a", "b"\]

$.tags\[:-3\].length()

2

$.odOrderDetailList\[0,1\].productName

"白医生中频针灸理疗仪家用医院医用多功能颈椎肩周炎腰肌劳损电疗经络激光低频按摩器同款中频激光综合治疗仪 2023新款", "测试SKU"

$.odOrderDetailList\[1\].\[productName,price\]

"测试SKU", 200

$..id

0,1,2

$.odOrderDetailList\[?(@.id == 4 - 0.4 * 5)\].productSku

"ESG03JJ1"

$.odOrderDetailList\[?(@.id == 1


$.extendInfo.templateInfo\[?(!(@.type == 2))\].code

"TPABC"

$.extendInfo.templateInfo\[?((@.type != 2))\].code

"TPABC"

$.odOrderDetailList\[?(@.price > 190)\].productName

"测试SKU"

$.odOrderDetailList\[?(@.id> $.id)\].productSku

\["38fjjjj","ESG03JJ1"\]

$..\[?(@.productSku)\]

[{"id":1,"productName":"白医生中频针灸理疗仪家用医院医用多功能颈椎肩周炎腰肌劳损电疗经络激光低频按摩器同款中频激光综合治疗仪 2023新款","quantity":1,"productSku":"38fjjjj","price":189.6},{"id":2,"productName":"测试SKU","quantity":3,"productSku":"ESG03JJ1","price":200}]

$..tags.length()

5

$.odOrderDetailList\[*\].price.min()

189.6

$..price.max()

200

作者:京东物流 马红岩

来源:京东云开发者社区 自猿其说 Tech 转载请注明来源

标签:Java,price,元素,Jayway,DSL,JsonPath,数组,匹配,odOrderDetailList
From: https://blog.51cto.com/u_15714439/8580661

相关文章

  • java List集合(ArrayList,LinkedList,Vector)
    Hii,mJinXiang⭐前言⭐本篇文章主要介绍java List集合的三种实现类ArrayList,LinkedList,Vector以及部分理论知识......
  • javaWeb 文件上传及下载
    前言网络上最常用的就是文件的上传和下载,本文讲解基于org.apache.commons.fileupload包及org.apache.commons.io包实现文件上传;通过设置响应头属性并基于文件流方式实现文件下载。一、文件上传1、实现思路文件上传是通过表单上传,因此首先需要判断表单中是否包含文件类型的标签,如......
  • Java Calendar日历类型常见方法
    #1.获取日期和时间:-`get(intfield)`:获取指定字段的值,如`Calendar.YEAR`获取年份,`Calendar.MONTH`获取月份等。-`getTime()`:获取日期对象对应的Date类型。#2.设置日期和时间:-`set(intfield,intvalue)`:设置指定字段的值,如`Calendar.YEAR`设置年份,`Calendar.MONTH`设置......
  • Java开发者的Python快速进修指南:网络编程及并发编程
    今天我们将对网络编程和多线程技术进行讲解,这两者的原理大家都已经了解了,因此我们主要关注的是它们的写法区别。虽然这些区别并不是非常明显,但我们之所以将网络编程和多线程一起讲解,是因为在学习Java的socket知识时,我们通常会将它们结合使用,以实现服务器对多个客户端连接的阻塞IO......
  • java基础学习:赋值运算符
    扩展的赋值运算符隐含了强制类型转换  packagecom.itheima.operator;publicclassQperator3{publicstaticvoidmain(String[]args){//目标:掌握扩展赋值运算符的使用//+=//需求类似于收红包doublea=9.5;dou......
  • 观察者模式--Java实现
    相关类图具体代码//Observer.javapackageorg.example.test019;publicinterfaceObserver{publicvoidbuy();publicvoidcry();}//Subject.javapackageorg.example.test019;importjava.util.ArrayList;publicabstractclassSubject{protect......
  • 状态模式--Java实现
    具体代码//Account.javapackageorg.example.test020;publicclassAccount{publicAccountStategetAccountState(){returnaccountState;}publicvoidsetAccountState(AccountStateaccountState){this.accountState=accountState;......
  • 策略模式--Java实现
    具体代码//Travel.javapackageorg.example.test021;publicinterfaceTravel{publicvoidtravel();}//Person.javapackageorg.example.test021;publicclassPerson{publicTravelgetTravel(){returntravel;}publicvoidsetTrav......
  • C++ 服务端与 Java 客户端的简单连接
    记录一下如何用两种语言简单通信,(其实也大差不差的,应该把。。。)//C++服务端#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>#include<iostream>#include<cstring>usingstd::cout;usingstd::endl;usingst......
  • Java开发者的Python快速进修指南:自定义模块及常用模块
    好的,按照我们平常的惯例,我先来讲一下今天这节课的内容,以及Java和Python在某些方面的相似之处。Python使用import语句来导入包,而Java也是如此。然而,两者之间的区别在于Python没有类路径的概念,它直接使用.py文件的文件名作为导入路径,并将其余的工作交给Python解释器来扫描和处理。另......