Kettle实战100篇 第17篇 JSONPath组件介绍说明

2024-05-08 20:48

本文主要是介绍Kettle实战100篇 第17篇 JSONPath组件介绍说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 表示法
    • 过滤器
    • 综合示例
      • 返回多个元素的JSONPath表达式的注意事项
    • Java使用示例
      • 简单使用
      • 返回预期
      • 过滤
        • 内联
        • 过滤
        • Roll Your Own
      • 值和路径
      • 配置信息
        • 选项
          • **DEFAULT_PATH_LEAF_TO_NULL**
          • ALWAYS_RETURN_LIST
          • **SUPPRESS_EXCEPTIONS**

在我们使用JSON input组件的时候,设置字段映射时,由于Kettle使用的是JSONPath组件来进行解析的,因此我们就需要了解他的相关语法

JSONPath是一个用于读取JSON的Java DSL操作库

GitHub:https://github.com/json-path/JsonPath

在线调试:http://jsonpath.herokuapp.com/

表示法

JSONPath表达式用于指定JSON结构元素(或一组元素)的路径.路径的表示法可以使用点表示,如下:

$.store.book[0].title

或者括号表示:

$['store']['book'][0]['title']

**$**所代表的是JSON根路径,在使用时可以忽略.例如$.foobar.namefoobar.name所表达的意思是一样的,同理$[0].status[0].status也一样

其他语法元素如下表:

表达式说明
$根对象或者数组
.property选择父对象中指定的属性
[property]选择父对象中的指定属性。务必在属性名称周围加上单引号。
如果属性名称包含空格等特殊字符,或者以A…Za…z_以外的字符开头,请使用此表示法
[n]从数组中选择第n个元素。索引从0开始。
[index1,index2,…]选择具有指定索引的数组元素。返回一个集合列表。
..property递归查找:递归搜索指定的属性名称,并返回具有此属性名称的所有值的数组。即使只找到一个属性,也始终返回一个列表。
*通配符选择对象或数组中的所有元素,无论其名称或索引如何。例如,address.*。*表示地址对象的所有属性,book [*]表示书籍数组的所有项目
[start:end] or [start:]从起始索引中选择数组元素,最多但不包括结束索引。如果省略end,则从开始到数组结束选择所有元素。返回一个列表。
[:n]选择数组的前n个元素。返回一个列表。
[-n:]选择数组的最后n个元素。返回一个列表。
[?expression]过滤表达式。选择对象或数组中与指定过滤器匹配的所有元素。返回一个列表。
[(expression)]可以使用脚本表达式代替显式属性名称或索引。一个例子是[(@.length-1)],它选择数组中的最后一项。这里,length指的是当前数组的长度,而不是名为length的JSON字段。
@在过滤器表达式中用于引用正在处理的当前节点。

注意:

  • JSONPath表达式(包括属性名称和值)区分大小写。
  • 与XPath不同,JSONPath没有用于从给定节点访问父节点或兄弟节点的操作。

过滤器

过滤器是用于过滤数组的逻辑表达式。带有过滤器的JSONPath表达式的示例

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

其中@表示当前正在处理的数组项或对象。过滤器也可以使用$来引用当前对象之外的属性

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

只指定属性名称的表达式如[?(@.isbn)]将匹配具有此属性的所有项目,无论值如何

此外,过滤器支持一下运算符

操作符说明
==等于,1和'1'被认为是相等的,字符串值必须用单引号括起来(不是双引号):例如[?(@.color=='red')]
!=不等于。字符串值必须用单引号括起来。
>大于
>=大于等于
<小于
<=小于等于
=~匹配JavaScript正则表达式,例如[?(@.description=~ /cat.*/i)]匹配描述以cat开头的项(不区分大小写)
!用于否定,例如[?(!@.isbn)]匹配没有isbn属性的项目
&&逻辑AND,用于组合多个过滤器表达式,例如:[?(@.category=='fiction' && @.price < 10 )]
||逻辑OR,用于组合多个过滤器表达式,例如:[?(@.category=='fiction' || @.price < 10 )]

综合示例

目前我们有如下JSON结构:

{"store": {"book": [{"category": "reference","author": "Nigel Rees","title": "Sayings of the Century","price": 8.95},{"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
}

在下面的例子中,$符号是可选的,可以省略掉:

表达式说明
$.store.*store对象下所有的属性(非递归)
$.store.bicycle.color获取得到color属性的值,结果为red
$.store..price
$..price
返回所有的price属性值集合,结果为[8.95,8.99,22.99,19.95]
$.store.book[*]
$..book[*]
所有的book集合
$..book[*].title返回book对象下的所有标题集合
$..book[0]返回第一个book集合对象,结果为[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}]
$..book[0].title返回第一个book集合对象中的title属性,结果是Sayings of the Century
$..book[0,1].title
$..book[:2].title
返回前2个book集合对象的title属性,结果是[Sayings of the Century, Moby Dick]
$..book[-1:].title
$..book[(@.length-1)].title
返回最后一个book对象的title属性集合,结果是[The Lord of the Rings]
$..book[?(@.author=='J.R.R. Tolkien')].title返回book集合中所有的作者等于J.R.R. Tolkien的title集合,结果是[The Lord of the Rings]
$..book[?(@.isbn)]返回所有book对象属性中含有isbn的属性,其结果是books集合
$..book[?(!@.isbn)]返回book对象属性中不包含isbn的属性,结果是集合
$..book[?(@.price < 10)]返回所有book对象属性中price属性小于10的对象集合
$..book[?(@.price > $.expensive)]返回所有book对象属性中price属性值大于expensive值的对象集合
$..book[?(@.author =~ /.*Tolkien/i)]返回所有book对象属性中的author属性是以Tolkien结尾(不区分大小写)的属性对象集合
$..book[?(@.category == 'fiction' || @.category == 'reference')]返回book对象属性中category等于fiction的或者等于reference的对象集合
$..*根目录下的JSON结构的所有成员(子对象,单个属性值,数组项)组合成一个数组。

返回多个元素的JSONPath表达式的注意事项

JSONPath查询不仅可以返回单个元素,还可以返回匹配元素的列表。

例如如下JSON结构:

{"name": "Rose Kolodny","phoneNumbers": [{"type": "home","number": "954-555-1234"},{"type": "work","number": "754-555-5678"}]
}

JSONPath表达式:

phoneNumbers[*].number

该表达式将会返回一个集合列表,如下:

[954-555-1234, 754-555-5678]

请注意,这不是JSON数组,它只是以逗号分隔的项列表,其中[]表示列表的开头和结尾。

对匹配列表使用“equals”断言时,请指定[]中包含的预期值列表,并用逗号和一个空格分隔

[apples, 15, false, ["foo","bar"], {"status":"ok"}]

除非引号是值的一部分,否则独立字符串(如apples)不应包含引号

示例

给定下面一个JSON:

{ "words": ["apples", "\"oranges\""] }

$ .words [*]返回所有数组项的列表,因此预期值为[apples,“oranges”]

注意与$ .words的区别,它返回JSON中显示的数组本身,因此,在这种情况下,值将是[“apples”,“\”oranges \“”]

作为JSON数组和对象的值保留内部引号,但是在它们的项之间缩小而没有空格:[“foo”,“bar”],而不是[ “foo” , “bar” ]

Java使用示例

因为我是一名Java工程师,看到这里,既然JSONPath是一个用Java语言开发的组件,那自然是要学习一下的(非Java语言的同学可以忽略~~~)

简单使用

首先在Maven项目中加入JSONPath的引用

<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency><groupId>com.jayway.jsonpath</groupId><artifactId>json-path</artifactId><version>2.4.0</version>
</dependency>

假设有如下JSON结构

{"name": "Rose Kolodny","phoneNumbers": [{"type": "home","number": "954-555-1234"},{"type": "work","number": "754-555-5678"}]
}

我们想获取得到number的数组集合,应该如何做呢

String json="...";
System.out.println("JSON:"+json);List<String> numbers= JsonPath.read(json,"$..number");
for (String num:numbers){System.out.println(num);
}
String name=JsonPath.read(json,"$.name");
System.out.println("name:"+name);

最终控制台输出:

954-555-1234
754-555-5678
Rose Kolodny

上面这种方式很麻烦,因为你没读取一个JSON的字段属性,都需要将源JSON整体传入到方法中,在对于程序性能来说是一种消耗,因为都需要JSONPath组件重新解析一次JSON的结构

如果你只想JSONPath只初始化一次就可以了,应该使用如下方式:

private static void once(String json){System.out.println("初始化一次");//初始化创建Document对象Object document= Configuration.defaultConfiguration().jsonProvider().parse(json);List<String> numbers= JsonPath.read(document,"$..number");for (String num:numbers){System.out.println(num);}String name=JsonPath.read(document,"$.name");System.out.println("name:"+name);
}

此外,JSONPath还提供了流式API,方便开发者使用

String json = "...";ReadContext ctx = JsonPath.parse(json);List<String> authorsOfBooksWithISBN = ctx.read("$.store.book[?(@.isbn)].author");List<Map<String, Object>> expensiveBooks = JsonPath.using(configuration).parse(json).read("$.store.book[?(@.price > 10)]", List.class);

返回预期

在使用JSONPath组件时,了解结果中的预期类型非常重要,比如在上个json中,我们查询name属性时,使用JSONPath的表达式$.name$..name就区别很大,一个是返回String类型的字符串,一个是返回数组,因此,根据JSONPath预判返回结果类型显得尤为关键。

//将会抛出java.lang.ClassCastException异常,因为这是返回一个String字符串的JSONPath表达式
List<String> list = JsonPath.parse(json).read("$.store.book[0].author")//正确执行
String author = JsonPath.parse(json).read("$.store.book[0].author")

在评估预判JSONPath的路径时,您需要了解路径何时确定的概念。如果路径包含,则路径是不确定的

  • ..:一个递归扫描的表示法
  • ?(<expression>):一个JSONPath表达式
  • [<number>,<number>(,<number>)]:多个数组索引

对于不确定的路径JSONPath始终返回一个数组列表

默认情况下,MappingProvider SPI提供了一个简单的对象映射器。这允许您指定所需的返回类型,MappingProvider将尝试执行映射。在下面的示例中,演示了Long和Date之间的映射

String json = "{\"date_as_long\" : 1411455611975}";Date date = JsonPath.parse(json).read("$['date_as_long']", Date.class);

如果将JSONPath配置为使用JacksonMappingProvider或者GsonMappingProvider,您甚至可以将JSONPath输出直接映射到POJO上

Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);

要获得完整的泛型类型信息,请使用TypeRef

TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};List<String> titles = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[*].title", typeRef);

过滤

有三种方法来创建JSONPath组件的过滤器规则

内联
List<Map<String, Object>> books =  JsonPath.parse(json).read("$.store.book[?(@.price < 10)]");

您可以使用&&||组合多个条件,[?(@.price < 10 && @.category == 'fiction')][?(@.category == 'reference' || @.price > 10)]

您也可以使用!表示非条件[?(!(@.price < 10 && @.category == 'fiction'))]

过滤

通过JSONPath提供的API来筛选

import static com.jayway.jsonpath.JsonPath.parse;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
...
...Filter cheapFictionFilter = filter(where("category").is("fiction").and("price").lte(10D)
);List<Map<String, Object>> books =  parse(json).read("$.store.book[?]", cheapFictionFilter);

注意占位符?对于路径中的过滤器。当提供多个过滤器时,它们将按顺序应用,其中占位符的数量必须与提供的过滤器数量相匹配。

您也可以使用ORAND对接过进行筛选组合

Filter fooOrBar = filter(where("foo").exists(true)).or(where("bar").exists(true)
);Filter fooAndBar = filter(where("foo").exists(true)).and(where("bar").exists(true)
);
Roll Your Own

第三种是实现你自己的Predicate接口

Predicate booksWithISBN = new Predicate() {@Overridepublic boolean apply(PredicateContext ctx) {return ctx.item(Map.class).containsKey("isbn");}
};List<Map<String, Object>> books = reader.read("$.store.book[?].isbn", List.class, booksWithISBN);

值和路径

在Goessner实现中,JsonPath可以返回Path或Value。值是默认值,以及上面的所有示例返回的内容。如果您更喜欢我们的查询所遇到的元素的路径,则可以使用选项来实现。

Configuration conf = Configuration.builder().options(Option.AS_PATH_LIST).build();List<String> pathList = using(conf).parse(json).read("$..author");assertThat(pathList).containsExactly("$['store']['book'][0]['author']","$['store']['book'][1]['author']","$['store']['book'][2]['author']","$['store']['book'][3]['author']");

配置信息

选项

创建配置时,有一些选项标志可以改变默认行为。

DEFAULT_PATH_LEAF_TO_NULL

此选项使JsonPath为缺少的叶子返回null。考虑以下json

[{"name" : "john","gender" : "male"},{"name" : "ben"}
]

Java代码

Configuration conf = Configuration.defaultConfiguration();//正确运行
String gender0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");
//PathNotFoundException thrown
String gender1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");Configuration conf2 = conf.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);//Works fine
String gender0 = JsonPath.using(conf2).parse(json).read("$[0]['gender']");
//返回null
String gender1 = JsonPath.using(conf2).parse(json).read("$[1]['gender']");
ALWAYS_RETURN_LIST

即使路径是确定的,此选项也会将JsonPath配置为返回列表

Configuration conf = Configuration.defaultConfiguration();//Works fine
List<String> genders0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");
//PathNotFoundException thrown
List<String> genders1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");
SUPPRESS_EXCEPTIONS

此选项可确保不会从路径评估传播任何异常。它遵循以下简单规则

  • 如果存在选项ALWAYS_RETURN_LIST,则将返回空列表
  • 如果选项ALWAYS_RETURN_LIST不存在,则返回null

这篇关于Kettle实战100篇 第17篇 JSONPath组件介绍说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971400

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}