欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中json處理工具JsonPath的使用教程

 更新時間:2023年08月30日 11:38:32   作者:movee  
JsonPath類似于XPath,是一種json數(shù)據(jù)結(jié)構(gòu)節(jié)點定位和導(dǎo)航表達式語言,這篇文章主要為大家介紹了JsonPath的基本使用,需要的小伙伴可以參考下

最近在思考構(gòu)建一個服務(wù)編排(Service Orchestration)系統(tǒng),考慮這個系統(tǒng)至少需要具備以下特征:

使用統(tǒng)一的方法定義服務(wù)功能單元

使用一種通用的方式將一個或多個服務(wù)的輸出映射到下游服務(wù)的輸入,映射時支持基礎(chǔ)的數(shù)據(jù)轉(zhuǎn)換與處理

支持以搭積木的方式將低層服務(wù)功能單元組織成更高層抽象的服務(wù)功能,直至一個完整的服務(wù)

用戶編排服務(wù)時,具備較大的靈活性定制業(yè)務(wù)

1 JsonPath是什么

json本質(zhì)上是一個樹形數(shù)據(jù)結(jié)構(gòu),同樣作為典型樹形數(shù)據(jù)結(jié)構(gòu)的xml文檔有XPathXML Path Language)這種廣泛使用的定位和選擇節(jié)點的表達式語言,java對象也有OGNLObject-Graph Navigation Language)這種對象屬性定位和導(dǎo)航表達式語言,JsonPath類似于XPath,是一種json數(shù)據(jù)結(jié)構(gòu)節(jié)點定位和導(dǎo)航表達式語言。

2 JsonPath的基本使用

2.1 JsonPath依賴

要使用JsonPath,需要在pom.xml文件中添加相應(yīng)的依賴:

2.2 json測試數(shù)據(jù)

為了便于說明,本文用到的json測試數(shù)據(jù),如果沒有特別說明,使用以下的json數(shù)據(jù):

{
    "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
        }
    },
    "expensive": 10
}

2.3 讀取json內(nèi)容

需要獲取指定json指定節(jié)點的數(shù)據(jù),提供json字符串和JsonPath表達式即可:

    // 讀取json字符串的expensive葉子節(jié)點的值
    Object expensive = JsonPath.read(jsonStr, "$.expensive");
    log.info("expensive value: {}, class: {}", expensive, expensive.getClass().getCanonicalName());
    // 讀取json字符串store節(jié)點下bicycle節(jié)點的值
    Object bicycle = JsonPath.read(jsonStr, "$.store.bicycle");
    log.info("bicycle value: {}, class: {}", bicycle, bicycle.getClass().getCanonicalName());
    // 讀取json字符串store下第一個book節(jié)點的值
    Object book = JsonPath.read(jsonStr, "$.store.book[0]");
    log.info("book value: {}, class: {}", book, book.getClass().getCanonicalName());
    // 讀取json字符串所有的author后代節(jié)點的值
    Object authors = JsonPath.read(jsonStr, "$..author");
    log.info("authors value: {}, class: {}", authors, authors.getClass().getCanonicalName());
    // 讀取json字符串中所有price值小于10的值
    Object books = JsonPath.read(jsonStr, "$.store.book[?(@.price < 10)]");
    log.info("books value: {}, class: {}", books, books.getClass().getCanonicalName());

輸出如下日志:

expensive value: 10, class: java.lang.Integer
bicycle value: {color=red, price=19.95}, class: java.util.LinkedHashMap
book value: {category=reference, author=Nigel Rees, title=Sayings of the Century, price=8.95}, class: java.util.LinkedHashMap
authors value: ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"], class: net.minidev.json.JSONArray
books value: [{"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}], class: net.minidev.json.JSONArray

2.3.1 基本語法

在JsonPath表達式語法中,$表示json頂層節(jié)點,.表示直接孩子,所以$.expensive表示json字符串的直接孩子節(jié)點expensive,節(jié)點也可以用[]表示。所以$['expensive']$.expensive等價。如果[]中是數(shù)字,則表示數(shù)組的某個元素,所以$.store.book[0]表示第1本書。數(shù)組支持切片,$.store.book[0:3]表示第1本到第3本書。..則表示任意的后代。*則表示所有的子節(jié)點。綜合起來如下表所示:

OperatorDescription
$The root element to query. This starts all path expressions.
@The current node being processed by a filter predicate.
*Wildcard. Available anywhere a name or numeric are required.
..Deep scan. Available anywhere a name is required.
.<name>Dot-notated child
['<name>' (, '<name>')]Bracket-notated child or children
[<number> (, <number>)]Array index or indexes
[start:end]Array slice operator
[?(<expression>)]Filter expression. Expression must evaluate to a boolean value.

JsonPath還支持根據(jù)條件過濾,表達式[?(expression)]中括號內(nèi)為條件表達式。表達式$.store.book[?(@.price < 10)]@表示遍歷到的當(dāng)前book,整個表達式就表示store中價格小于10的所有的book。

JsonPath的條件表達式支持以下操作符:

OperatorDescription
==left is equal to right (note that 1 is not equal to '1')
!=left is not equal to right
<left is less than right
<=left is less or equal to right
left is greater than right
>=left is greater than or equal to right
=~left matches regular expression [?(@.name =~ /foo.*?/i)]
inleft exists in right [?(@.size in ['S', 'M'])]
ninleft does not exists in right
subsetofleft is a subset of right [?(@.sizes subsetof ['S', 'M', 'L'])]
anyofleft has an intersection with right [?(@.sizes anyof ['M', 'L'])]
noneofleft has no intersection with right [?(@.sizes noneof ['M', 'L'])]
sizesize of left (array or string) should match right
emptyleft (array or string) should be empty

當(dāng)然一些常用的filter函數(shù)也是要支持的:

FunctionDescriptionOutput type
min()Provides the min value of an array of numbersDouble
max()Provides the max value of an array of numbersDouble
avg()Provides the average value of an array of numbersDouble
stddev()Provides the standard deviation value of an array of numbersDouble
length()Provides the length of an arrayInteger
sum()Provides the sum value of an array of numbersDouble
keys()Provides the property keys (An alternative for terminal tilde ~)Set<E>
concat(X)Provides a concatinated version of the path output with a new itemlike input
append(X)add an item to the json path output arraylike input
first()Provides the first item of an arrayDepends on the array
last()Provides the last item of an arrayDepends on the array
index(X)Provides the item of an array of index: X, if the X is negative, take from backwardsDepends on the array
Filter Operators

詳細的JsonPath表達式語法和支持的過濾條件請參考github官方文檔,文檔本身介紹的已經(jīng)很詳細了。

2.3.2 返回值

從上面的日志結(jié)果來看,JsonPath的返回結(jié)果的數(shù)據(jù)類型依情況而定,大概情況是(具體實際情況與底層使用的Json處理組件相關(guān)):

  • 如果結(jié)果是json葉子節(jié)點,則是葉子節(jié)點對應(yīng)的基本數(shù)據(jù)類型
  • 如果是數(shù)組,則是JSONArray
  • 如果是對象,這是LinkedHashMap

2.3.3 指定返回值類型

JsonPath也支持指定返回值類型,類似于json反序列化

Long expensive = JsonPath.parse(jsonStr).read("$.expensive", Long.class);
Bicycle bicycle = JsonPath.parse(jsonStr).read("$.store.bicycle", Bicycle.class);

如果json底層處理組件是jackson或gson,還可以支持泛型,假如使用jackson,先添加jackson-databind依賴:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>

然后配置使用jackson進行json處理和映射即可,如下所示:

Configuration.setDefaults(new Configuration.Defaults() {
    // 底層使用jackson
    private final JsonProvider jsonProvider = new JacksonJsonProvider();
    private final MappingProvider mappingProvider = new JacksonMappingProvider();
    @Override
    public JsonProvider jsonProvider() {
        return jsonProvider;
    }
    @Override
    public MappingProvider mappingProvider() {
        return mappingProvider;
    }
    @Override
    public Set<Option> options() {
        return EnumSet.noneOf(Option.class);
    }
});
TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};
List<String> authors = JsonPath.parse(jsonStr).read("$..author", typeRef);

2.4 修改json的值

2.4.1 為節(jié)點設(shè)置新值

Object book = JsonPath.read(jsonStr, "$.store.book[0]");
String target = "{\"x\": 128}";
String modified = JsonPath.parse(target).set("$.x", book).jsonString();

輸出:

modified: {"x":{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}}

可見目標(biāo)json字符串的節(jié)點x的值替換為了book的值,新的值與原先的值可以是完全不同的類型

2.4.2 為對象節(jié)點添加新的子節(jié)點

下面的例子為target json字符串添加了一個名字為k的子節(jié)點。注意,這個方法只能作用于json對象,不能是葉子節(jié)點或數(shù)組

Object book = JsonPath.read(jsonStr, "$.store.book[0]");
String target = "{\"x\": 128}";
String modified = JsonPath.parse(target).put("$", "k", book).jsonString();

2.4.3 對數(shù)組添加新的元素

String target = "{\"x\": [128]}";
String modified = JsonPath.parse(target).put("$.x", 300).jsonString();

2.4.4 重命名節(jié)點名字

String target = "{\"x\": [128]}";
String modified = JsonPath.parse(target).renameKey("$", "x", "y").jsonString();

2.4.5 刪除

String target = "{\"x\": [128]}";
String modified = JsonPath.parse(target).delete("$.x").jsonString();

3 JsonPath的高級特性

3.1 進一步配置你的JsonPath

JsonPath提供了一些配置項來調(diào)整它的功能,這些配置項配置在Option枚舉類中,如下所示:

public enum Option {
    DEFAULT_PATH_LEAF_TO_NULL,
    ALWAYS_RETURN_LIST,
    AS_PATH_LIST,
    SUPPRESS_EXCEPTIONS,
    REQUIRE_PROPERTIES
}

功能說明:

  • DEFAULT_PATH_LEAF_TO_NULL:當(dāng)路徑表達的節(jié)點不存在時,不拋出異常,而是返回null值
  • ALWAYS_RETURN_LIST:返回值總是一個list,即使路徑找到的是單個值
  • AS_PATH_LIST:返回找到節(jié)點的路徑,而不是節(jié)點的值
  • SUPPRESS_EXCEPTIONS:異常時不拋出異常

使用配置:

Configuration conf = Configuration.builder()
   .options(Option.AS_PATH_LIST).build();
List<String> pathList = JsonPath.using(conf).parse(jsonStr).read("$..author");
// 返回的是author節(jié)點的路徑列表
assertThat(pathList).containsExactly(
    "$['store']['book'][0]['author']",
    "$['store']['book'][1]['author']",
    "$['store']['book'][2]['author']",
    "$['store']['book'][3]['author']");

3.2 修改json底層處理組件

JsonPath支持多個json組件,默認使用的是JsonSmartJsonProvider,其他的還包括:

JacksonJsonProvider
JacksonJsonNodeJsonProvider
GsonJsonProvider
JsonOrgJsonProvider
JakartaJsonProvider

使用下面的方式可以修改默認的json provider:

Configuration.setDefaults(new Configuration.Defaults() {
    private final JsonProvider jsonProvider = new JacksonJsonProvider();
    private final MappingProvider mappingProvider = new JacksonMappingProvider();
    @Override
    public JsonProvider jsonProvider() {
        return jsonProvider;
    }
    @Override
    public MappingProvider mappingProvider() {
        return mappingProvider;
    }
    @Override
    public Set<Option> options() {
        return EnumSet.noneOf(Option.class);
    }
});

3.3 性能優(yōu)化

如下的方式每次都需要解析json字符串:

Object book = JsonPath.read(jsonStr, "$.store.book[0]");

可以先解析json字符串,然后在查找,這樣只需要解析一次:

DocumentContext context = JsonPath.parse(jsonStr)
Long expensive = context.read("$.expensive", Long.class);
Bicycle bicycle = context.read("$.store.bicycle", Bicycle.class);

還可以使用cache,JsonPath已經(jīng)提供了兩個cache:

com.jayway.jsonpath.spi.cache.LRUCache (default, thread safe)
com.jayway.jsonpath.spi.cache.NOOPCache (no cache)

我們可以這樣配置使用cache:

CacheProvider.setCache(new LRUCache(100));

或者配置一個我們自己實現(xiàn)的cache:

CacheProvider.setCache(new Cache() {
    //Not thread safe simple cache
    private Map<String, JsonPath> map = new HashMap<String, JsonPath>();
    @Override
    public JsonPath get(String key) {
        return map.get(key);
    }
    @Override
    public void put(String key, JsonPath jsonPath) {
        map.put(key, jsonPath);
    }
});

到此這篇關(guān)于Java中json處理工具JsonPath的使用教程的文章就介紹到這了,更多相關(guān)Java JsonPath內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • @RequestBody注解Ajax post json List集合數(shù)據(jù)請求400/415的處理

    @RequestBody注解Ajax post json List集合數(shù)據(jù)請求400/41

    這篇文章主要介紹了@RequestBody注解Ajax post json List集合數(shù)據(jù)請求400/415的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 新手初學(xué)Java網(wǎng)絡(luò)編程

    新手初學(xué)Java網(wǎng)絡(luò)編程

    網(wǎng)絡(luò)編程是指編寫運行在多個設(shè)備(計算機)的程序,這些設(shè)備都通過網(wǎng)絡(luò)連接起來。本文介紹了一些網(wǎng)絡(luò)編程基礎(chǔ)的概念,并用Java來實現(xiàn)TCP和UDP的Socket的編程,來讓讀者更好的了解其原理
    2021-07-07
  • SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置問題及解決方法

    SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置問題及解決方法

    這篇文章主要介紹了SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置,我們可以通過自定義配置數(shù)據(jù)庫配置類來解決這個問題,方式有很多,不同的業(yè)務(wù)采用的方式也不同,下面我簡單的介紹我們項目的使用的方法
    2022-06-06
  • Java通俗易懂系列設(shè)計模式之觀察者模式

    Java通俗易懂系列設(shè)計模式之觀察者模式

    這篇文章主要介紹了Java通俗易懂系列設(shè)計模式之觀察者模式,對設(shè)計模式感興趣的同學(xué),一定要看一下
    2021-04-04
  • Java+Springboot搭建一個在線網(wǎng)盤文件分享系統(tǒng)

    Java+Springboot搭建一個在線網(wǎng)盤文件分享系統(tǒng)

    本主要介紹了通過springboot+freemark+jpa+MySQL實現(xiàn)的在線網(wǎng)盤文件分享系統(tǒng),其功能跟百度網(wǎng)盤非常類似,可以實現(xiàn)文件的上傳、移動、復(fù)制、下載等,需要的可以參考一下
    2021-11-11
  • Java實戰(zhàn)之課程信息管理系統(tǒng)的實現(xiàn)

    Java實戰(zhàn)之課程信息管理系統(tǒng)的實現(xiàn)

    這篇文章主要介紹了如何利用Java實現(xiàn)課程信息管理系統(tǒng),文中采用到的技術(shù)有:Springboot、SpringMVC、MyBatis、FreeMarker等,感興趣的可以了解一下
    2022-04-04
  • Springboot?配置SqlSessionFactory方式

    Springboot?配置SqlSessionFactory方式

    這篇文章主要介紹了Springboot?配置SqlSessionFactory方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 淺談如何優(yōu)雅地停止Spring Boot應(yīng)用

    淺談如何優(yōu)雅地停止Spring Boot應(yīng)用

    這篇文章主要介紹了淺談如何優(yōu)雅地停止Spring Boot應(yīng)用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • SpringBoot2.6.x 與 Swagger3 兼容問題及解決方法

    SpringBoot2.6.x 與 Swagger3 兼容問題及解決方法

    文章介紹了Spring Boot 2.6.x與Swagger 3兼容性問題的解決方法,如果項目中未引入spring-boot-starter-actuator,則在yml文件中加入相關(guān)配置,反之,需要添加其他配置,感興趣的朋友一起看看吧
    2025-03-03
  • Java設(shè)計模式之迭代器模式解析

    Java設(shè)計模式之迭代器模式解析

    這篇文章主要介紹了Java設(shè)計模式之迭代器模式解析,迭代器模式提供一個對象來順序訪問聚合對象中的一系列數(shù)據(jù),而不暴露聚合對象的內(nèi)部表示,本文提供了部分代碼,需要的朋友可以參考下
    2023-09-09

最新評論