免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Kettle實(shí)戰(zhàn)100篇 第17篇 JSONPath組件介紹說(shuō)明

文章目錄

    • 表示法
    • 過(guò)濾器
    • 綜合示例
      • 返回多個(gè)元素的JSONPath表達(dá)式的注意事項(xiàng)
    • Java使用示例
      • 簡(jiǎn)單使用
      • 返回預(yù)期
      • 過(guò)濾
        • 內(nèi)聯(lián)
        • 過(guò)濾
        • Roll Your Own
      • 值和路徑
      • 配置信息
        • 選項(xiàng)
          • **DEFAULT_PATH_LEAF_TO_NULL**
          • ALWAYS_RETURN_LIST
          • **SUPPRESS_EXCEPTIONS**

在我們使用JSON input組件的時(shí)候,設(shè)置字段映射時(shí),由于Kettle使用的是JSONPath組件來(lái)進(jìn)行解析的,因此我們就需要了解他的相關(guān)語(yǔ)法

JSONPath是一個(gè)用于讀取JSON的Java DSL操作庫(kù)

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

在線調(diào)試:http://jsonpath.herokuapp.com/

表示法

JSONPath表達(dá)式用于指定JSON結(jié)構(gòu)元素(或一組元素)的路徑.路徑的表示法可以使用點(diǎn)表示,如下:

$.store.book[0].title

或者括號(hào)表示:

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

**$**所代表的是JSON根路徑,在使用時(shí)可以忽略.例如$.foobar.namefoobar.name所表達(dá)的意思是一樣的,同理$[0].status[0].status也一樣

其他語(yǔ)法元素如下表:

表達(dá)式說(shuō)明
$根對(duì)象或者數(shù)組
.property選擇父對(duì)象中指定的屬性
[property]選擇父對(duì)象中的指定屬性。務(wù)必在屬性名稱周圍加上單引號(hào)。
如果屬性名稱包含空格等特殊字符,或者以A…Za…z_以外的字符開頭,請(qǐng)使用此表示法
[n]從數(shù)組中選擇第n個(gè)元素。索引從0開始。
[index1,index2,…]選擇具有指定索引的數(shù)組元素。返回一個(gè)集合列表。
..property遞歸查找:遞歸搜索指定的屬性名稱,并返回具有此屬性名稱的所有值的數(shù)組。即使只找到一個(gè)屬性,也始終返回一個(gè)列表。
*通配符選擇對(duì)象或數(shù)組中的所有元素,無(wú)論其名稱或索引如何。例如,address.*。*表示地址對(duì)象的所有屬性,book [*]表示書籍?dāng)?shù)組的所有項(xiàng)目
[start:end] or [start:]從起始索引中選擇數(shù)組元素,最多但不包括結(jié)束索引。如果省略end,則從開始到數(shù)組結(jié)束選擇所有元素。返回一個(gè)列表。
[:n]選擇數(shù)組的前n個(gè)元素。返回一個(gè)列表。
[-n:]選擇數(shù)組的最后n個(gè)元素。返回一個(gè)列表。
[?expression]過(guò)濾表達(dá)式。選擇對(duì)象或數(shù)組中與指定過(guò)濾器匹配的所有元素。返回一個(gè)列表。
[(expression)]可以使用腳本表達(dá)式代替顯式屬性名稱或索引。一個(gè)例子是[(@.length-1)],它選擇數(shù)組中的最后一項(xiàng)。這里,length指的是當(dāng)前數(shù)組的長(zhǎng)度,而不是名為length的JSON字段。
@在過(guò)濾器表達(dá)式中用于引用正在處理的當(dāng)前節(jié)點(diǎn)。

注意:

  • JSONPath表達(dá)式(包括屬性名稱和值)區(qū)分大小寫。
  • 與XPath不同,JSONPath沒(méi)有用于從給定節(jié)點(diǎn)訪問(wèn)父節(jié)點(diǎn)或兄弟節(jié)點(diǎn)的操作。

過(guò)濾器

過(guò)濾器是用于過(guò)濾數(shù)組的邏輯表達(dá)式。帶有過(guò)濾器的JSONPath表達(dá)式的示例

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

其中@表示當(dāng)前正在處理的數(shù)組項(xiàng)或?qū)ο蟆_^(guò)濾器也可以使用$來(lái)引用當(dāng)前對(duì)象之外的屬性

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

只指定屬性名稱的表達(dá)式如[?(@.isbn)]將匹配具有此屬性的所有項(xiàng)目,無(wú)論值如何

此外,過(guò)濾器支持一下運(yùn)算符

操作符說(shuō)明
==等于,1和'1'被認(rèn)為是相等的,字符串值必須用單引號(hào)括起來(lái)(不是雙引號(hào)):例如[?(@.color=='red')]
!=不等于。字符串值必須用單引號(hào)括起來(lái)。
>大于
>=大于等于
<小于
<=小于等于
=~匹配JavaScript正則表達(dá)式,例如[?(@.description=~ /cat.*/i)]匹配描述以cat開頭的項(xiàng)(不區(qū)分大小寫)
!用于否定,例如[?(!@.isbn)]匹配沒(méi)有isbn屬性的項(xiàng)目
&&邏輯AND,用于組合多個(gè)過(guò)濾器表達(dá)式,例如:[?(@.category=='fiction' && @.price < 10 )]
||邏輯OR,用于組合多個(gè)過(guò)濾器表達(dá)式,例如:[?(@.category=='fiction' || @.price < 10 )]

綜合示例

目前我們有如下JSON結(jié)構(gòu):

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

在下面的例子中,$符號(hào)是可選的,可以省略掉:

表達(dá)式說(shuō)明
$.store.*store對(duì)象下所有的屬性(非遞歸)
$.store.bicycle.color獲取得到color屬性的值,結(jié)果為red
$.store..price
$..price
返回所有的price屬性值集合,結(jié)果為[8.95,8.99,22.99,19.95]
$.store.book[*]
$..book[*]
所有的book集合
$..book[*].title返回book對(duì)象下的所有標(biāo)題集合
$..book[0]返回第一個(gè)book集合對(duì)象,結(jié)果為[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}]
$..book[0].title返回第一個(gè)book集合對(duì)象中的title屬性,結(jié)果是Sayings of the Century
$..book[0,1].title
$..book[:2].title
返回前2個(gè)book集合對(duì)象的title屬性,結(jié)果是[Sayings of the Century, Moby Dick]
$..book[-1:].title
$..book[(@.length-1)].title
返回最后一個(gè)book對(duì)象的title屬性集合,結(jié)果是[The Lord of the Rings]
$..book[?(@.author=='J.R.R. Tolkien')].title返回book集合中所有的作者等于J.R.R. Tolkien的title集合,結(jié)果是[The Lord of the Rings]
$..book[?(@.isbn)]返回所有book對(duì)象屬性中含有isbn的屬性,其結(jié)果是books集合
$..book[?(!@.isbn)]返回book對(duì)象屬性中不包含isbn的屬性,結(jié)果是集合
$..book[?(@.price < 10)]返回所有book對(duì)象屬性中price屬性小于10的對(duì)象集合
$..book[?(@.price > $.expensive)]返回所有book對(duì)象屬性中price屬性值大于expensive值的對(duì)象集合
$..book[?(@.author =~ /.*Tolkien/i)]返回所有book對(duì)象屬性中的author屬性是以Tolkien結(jié)尾(不區(qū)分大小寫)的屬性對(duì)象集合
$..book[?(@.category == 'fiction' || @.category == 'reference')]返回book對(duì)象屬性中category等于fiction的或者等于reference的對(duì)象集合
$..*根目錄下的JSON結(jié)構(gòu)的所有成員(子對(duì)象,單個(gè)屬性值,數(shù)組項(xiàng))組合成一個(gè)數(shù)組。

返回多個(gè)元素的JSONPath表達(dá)式的注意事項(xiàng)

JSONPath查詢不僅可以返回單個(gè)元素,還可以返回匹配元素的列表。

例如如下JSON結(jié)構(gòu):

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

JSONPath表達(dá)式:

phoneNumbers[*].number

該表達(dá)式將會(huì)返回一個(gè)集合列表,如下:

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

請(qǐng)注意,這不是JSON數(shù)組,它只是以逗號(hào)分隔的項(xiàng)列表,其中[]表示列表的開頭和結(jié)尾。

對(duì)匹配列表使用“equals”斷言時(shí),請(qǐng)指定[]中包含的預(yù)期值列表,并用逗號(hào)和一個(gè)空格分隔

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

除非引號(hào)是值的一部分,否則獨(dú)立字符串(如apples)不應(yīng)包含引號(hào)

示例

給定下面一個(gè)JSON:

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

$ .words [*]返回所有數(shù)組項(xiàng)的列表,因此預(yù)期值為[apples,“oranges”]。

注意與$ .words的區(qū)別,它返回JSON中顯示的數(shù)組本身,因此,在這種情況下,值將是[“apples”,“\”oranges \“”]

作為JSON數(shù)組和對(duì)象的值保留內(nèi)部引號(hào),但是在它們的項(xiàng)之間縮小而沒(méi)有空格:[“foo”,“bar”],而不是[ “foo” , “bar” ]。

Java使用示例

因?yàn)槲沂且幻鸍ava工程師,看到這里,既然JSONPath是一個(gè)用Java語(yǔ)言開發(fā)的組件,那自然是要學(xué)習(xí)一下的(非Java語(yǔ)言的同學(xué)可以忽略~~~)

簡(jiǎn)單使用

首先在Maven項(xiàng)目中加入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>

假設(shè)有如下JSON結(jié)構(gòu)

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

我們想獲取得到number的數(shù)組集合,應(yīng)該如何做呢

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

最終控制臺(tái)輸出:

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

上面這種方式很麻煩,因?yàn)槟銢](méi)讀取一個(gè)JSON的字段屬性,都需要將源JSON整體傳入到方法中,在對(duì)于程序性能來(lái)說(shuō)是一種消耗,因?yàn)槎夹枰狫SONPath組件重新解析一次JSON的結(jié)構(gòu)

如果你只想JSONPath只初始化一次就可以了,應(yīng)該使用如下方式:

private static void once(String json){
    System.out.println("初始化一次");
    //初始化創(chuàng)建Document對(duì)象
    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,方便開發(fā)者使用

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

返回預(yù)期

在使用JSONPath組件時(shí),了解結(jié)果中的預(yù)期類型非常重要,比如在上個(gè)json中,我們查詢name屬性時(shí),使用JSONPath的表達(dá)式$.name$..name就區(qū)別很大,一個(gè)是返回String類型的字符串,一個(gè)是返回?cái)?shù)組,因此,根據(jù)JSONPath預(yù)判返回結(jié)果類型顯得尤為關(guān)鍵。

//將會(huì)拋出java.lang.ClassCastException異常,因?yàn)檫@是返回一個(gè)String字符串的JSONPath表達(dá)式
List<String> list = JsonPath.parse(json).read("$.store.book[0].author")

//正確執(zhí)行
String author = JsonPath.parse(json).read("$.store.book[0].author")

在評(píng)估預(yù)判JSONPath的路徑時(shí),您需要了解路徑何時(shí)確定的概念。如果路徑包含,則路徑是不確定的

  • ..:一個(gè)遞歸掃描的表示法
  • ?(<expression>):一個(gè)JSONPath表達(dá)式
  • [<number>,<number>(,<number>)]:多個(gè)數(shù)組索引

對(duì)于不確定的路徑JSONPath始終返回一個(gè)數(shù)組列表

默認(rèn)情況下,MappingProvider SPI提供了一個(gè)簡(jiǎn)單的對(duì)象映射器。這允許您指定所需的返回類型,MappingProvider將嘗試執(zhí)行映射。在下面的示例中,演示了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);

要獲得完整的泛型類型信息,請(qǐng)使用TypeRef

TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};

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

過(guò)濾

有三種方法來(lái)創(chuàng)建JSONPath組件的過(guò)濾器規(guī)則

內(nèi)聯(lián)

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

您可以使用&&||組合多個(gè)條件,[?(@.price < 10 && @.category == 'fiction')][?(@.category == 'reference' || @.price > 10)]

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

過(guò)濾

通過(guò)JSONPath提供的API來(lái)篩選

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

注意占位符?對(duì)于路徑中的過(guò)濾器。當(dāng)提供多個(gè)過(guò)濾器時(shí),它們將按順序應(yīng)用,其中占位符的數(shù)量必須與提供的過(guò)濾器數(shù)量相匹配。

您也可以使用ORAND對(duì)接過(guò)進(jìn)行篩選組合

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

第三種是實(shí)現(xiàn)你自己的Predicate接口

Predicate booksWithISBN = new Predicate() {
    @Override
    public 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實(shí)現(xiàn)中,JsonPath可以返回Path或Value。值是默認(rèn)值,以及上面的所有示例返回的內(nèi)容。如果您更喜歡我們的查詢所遇到的元素的路徑,則可以使用選項(xiàng)來(lái)實(shí)現(xiàn)。

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']");

配置信息

選項(xiàng)

創(chuàng)建配置時(shí),有一些選項(xiàng)標(biāo)志可以改變默認(rèn)行為。

DEFAULT_PATH_LEAF_TO_NULL

此選項(xiàng)使JsonPath為缺少的葉子返回null??紤]以下json

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

Java代碼

Configuration conf = Configuration.defaultConfiguration();

//正確運(yùn)行
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

即使路徑是確定的,此選項(xiàng)也會(huì)將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

此選項(xiàng)可確保不會(huì)從路徑評(píng)估傳播任何異常。它遵循以下簡(jiǎn)單規(guī)則

  • 如果存在選項(xiàng)ALWAYS_RETURN_LIST,則將返回空列表
  • 如果選項(xiàng)ALWAYS_RETURN_LIST不存在,則返回null
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
技術(shù)必備:推薦一款接口自動(dòng)化測(cè)試數(shù)據(jù)校驗(yàn)神器
Struts2-Json-Plugin 的使用
python接口自動(dòng)化39-JMESPath解析json數(shù)據(jù)
json解析神器 jsonpath的使用
JSON.stringify()、JSON.parse()和eval(string)
關(guān)于學(xué)習(xí)json的總結(jié)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服