最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot使用JSONPath實(shí)現(xiàn)高效處理JSON數(shù)據(jù)

 更新時(shí)間:2026年01月15日 11:51:52   作者:風(fēng)象南  
在日常開發(fā)中,我們經(jīng)常需要處理 JSON 數(shù)據(jù),特別是從復(fù)雜的 JSON 結(jié)構(gòu)中提取特定字段,下面我們就來看看如何使用SpringBoot和JSONPath實(shí)現(xiàn)處理JSON數(shù)據(jù)吧

前言

在日常開發(fā)中,我們經(jīng)常需要處理 JSON 數(shù)據(jù),特別是從復(fù)雜的 JSON 結(jié)構(gòu)中提取特定字段。傳統(tǒng)的處理方式如 Gson、Jackson 的 API 雖然功能強(qiáng)大,但在處理復(fù)雜路徑提取時(shí)代碼往往顯得冗長且不易維護(hù)。

今天給大家介紹一個(gè)更優(yōu)雅的解決方案 —— JSONPath,它就像 JSON 界的 XPath,讓我們可以用簡潔的路徑表達(dá)式來定位和提取 JSON 數(shù)據(jù)。

什么是 JSONPath

JSONPath 是一種用于從 JSON 文檔中提取特定數(shù)據(jù)的查詢語言。它的語法簡潔直觀,類似于 JavaScript 對(duì)象屬性的訪問方式。

常用 JSONPath 語法

表達(dá)式說明
$根節(jié)點(diǎn)
@當(dāng)前節(jié)點(diǎn)
. 或 []子節(jié)點(diǎn)操作符
..遞歸下降(任意深度)
*通配符,匹配所有成員/元素
[]下標(biāo)運(yùn)算符
[start:end]數(shù)組切片
[?()]過濾表達(dá)式

Spring Boot 集成 JSONPath

1. 添加依賴

pom.xml 中添加 JSONPath 依賴:

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.9.0</version>
</dependency>

2. 基礎(chǔ)使用示例

首先準(zhǔn)備一個(gè) JSON 示例:

{
  "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
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

讀取數(shù)據(jù)

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.PathNotFoundException;

public class JsonPathExample {

    private String json = "..."; // 上述 JSON 字符串

    @Test
    public void testReadJson() {
        // 獲取所有書籍的作者
        List<String> authors = JsonPath.parse(json)
            .read("$.store.book[*].author");

        // 獲取第一本書的價(jià)格
        Double price = JsonPath.parse(json)
            .read("$.store.book[0].price");

        // 獲取所有價(jià)格低于10元的書籍
        List<Map> cheapBooks = JsonPath.parse(json)
            .read("$.store.book[?(@.price < 10)]");

        // 獲取最后一本書
        Map lastBook = JsonPath.parse(json)
            .read("$.store.book[-1]");
    }
}

在 Spring Boot 中的實(shí)際應(yīng)用

import org.springframework.web.bind.annotation.*;
import com.jayway.jsonpath.JsonPath;

@RestController
@RequestMapping("/api")
public class BookController {

    @PostMapping("/extract")
    public ResponseEntity<?> extractData(@RequestBody String jsonString) {
        try {
            // 提取所有書籍標(biāo)題
            List<String> titles = JsonPath.parse(jsonString)
                .read("$.store.book[*].title");

            // 提取價(jià)格區(qū)間內(nèi)的書籍
            List<Map> books = JsonPath.parse(jsonString)
                .read("$.store.book[?(@.price >= 8 && @.price <= 12)]");

            return ResponseEntity.ok(Map.of(
                "titles", titles,
                "filteredBooks", books
            ));
        } catch (PathNotFoundException e) {
            return ResponseEntity.badRequest()
                .body("JSON路徑不存在: " + e.getMessage());
        }
    }

    @GetMapping("/authors")
    public ResponseEntity<?> getAuthors(@RequestParam String jsonData) {
        List<String> authors = JsonPath.parse(jsonData)
            .read("$.store.book[*].author");
        return ResponseEntity.ok(authors);
    }
}

3. 高級(jí)用法

自定義配置

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Option;

@Configuration
public class JsonPathConfig {

    public Configuration jsonPathConfiguration() {
        return Configuration.builder()
            // 抑制異常,返回 null
            .options(Option.SUPPRESS_EXCEPTIONS)
            // 默認(rèn)值為空集合
            .options(Option.DEFAULT_PATH_LEAF_TO_NULL)
            // 總是返回列表
            .options(Option.ALWAYS_RETURN_LIST)
            // 緩存
            .options(Option.CACHE)
            .build();
    }
}

緩存解析結(jié)果

@Service
public class JsonPathCacheService {

    private final Map<String, Object> cache = new ConcurrentHashMap<>();

    public Object readWithCache(String json, String path) {
        return JsonPath.using(Configuration.defaultConfiguration())
            .parse(json)
            .read(path);
    }

    // 預(yù)編譯路徑,提升性能
    private final JsonPath compiledPath = JsonPath.compile("$.store.book[*]");

    public List<Map> readOptimized(String json) {
        return compiledPath.read(json);
    }
}

與 REST 調(diào)用結(jié)合

@Service
public class ExternalApiService {

    private final RestTemplate restTemplate;

    public List<String> extractFromExternalApi(String url, String jsonPath) {
        String response = restTemplate.getForObject(url, String.class);
        return JsonPath.parse(response).read(jsonPath);
    }
}

過濾表達(dá)式詳解

// 價(jià)格大于10的書籍
$.store.book[?(@.price > 10)]

// category 為 fiction 的書籍
$.store.book[?(@.category == 'fiction')]

// 包含 isbn 字段的書籍
$.store.book[?(@.isbn)]

// 正則匹配
$.store.book[?(@.author =~ /.*Melville.*/)]

// 多條件組合
$.store.book[?(@.price < 10 && @.category == 'fiction')]

除了 Jayway JsonPath,常見的 JSON 處理庫也有各自的 JSONPath 或類似功能實(shí)現(xiàn)。

FastJSON - 內(nèi)置 JSONPath

FastJSON內(nèi)置了 JSONPath 支持,使用起來非常簡潔。

添加依賴

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.53</version>
</dependency>

使用示例

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONPath;
import com.alibaba.fastjson2.JSONObject;

public class FastJsonPathExample {

    private String json = "..."; // 同上 JSON 示例

    @Test
    public void testFastJsonPath() {
        JSONObject object = JSON.parseObject(json);

        // 獲取所有書籍作者
        List<String> authors = (List<String>) JSONPath.eval(object, "$.store.book[*].author");

        // 獲取第一本書價(jià)格
        Double price = (Double) JSONPath.eval(object, "$.store.book[0].price");

        // 過濾價(jià)格小于10的書籍
        List books = (List) JSONPath.eval(object, "$.store.book[?(@.price < 10)]");

        // size 方法
        Integer size = (Integer) JSONPath.eval(object, "$.store.book.size()");

        // 獲取所有包含 isbn 的書籍
        List booksWithIsbn = (List) JSONPath.eval(object, "$.store.book[?(@.isbn)]");
    }
}

FastJSON JSONPath 多種查詢方式

FastJSON 提供了多種查詢方式,適應(yīng)不同場景:

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONPath;
import com.alibaba.fastjson2.JSONObject;

public class FastJsonPathQueryExample {

    private JSONObject object = JSON.parseObject(json);

    @Test
    public void testDifferentQueryMethods() {

        // ========== 方式一:JSONPath.eval(靜態(tài)方法,最常用)==========
        List authors1 = (List) JSONPath.eval(object, "$.store.book[*].author");


        // ========== 方式二:JSONPath.of + extract(推薦,性能更好)==========
        // 預(yù)編譯路徑表達(dá)式,性能更優(yōu)(適合重復(fù)使用)
        JSONPath path = JSONPath.of("$.store.book[*].author");
        List authors2 = (List) path.extract(object);


        // ========== 方式三:compile + eval(另一種編譯方式)==========
        JSONPath compiledPath = JSONPath.compile("$.store.book[*].author");
        List authors3 = (List) compiledPath.eval(object);


        // ========== 方式四:路徑對(duì)象直接調(diào)用 set(修改操作)==========
        JSONPath pricePath = JSONPath.of("$.store.book[0].price");
        pricePath.set(object, 88.88);


        // ========== 方式五:contains(判斷是否包含路徑)==========
        boolean hasBook = JSONPath.contains(object, "$.store.book");
        boolean hasIsbn = JSONPath.contains(object, "$.store.book[2].isbn");


        // ========== 方式六:size(獲取數(shù)組大?。?=========
        Integer arraySize = (Integer) JSONPath.eval(object, "$.store.book.size()");
        // 或者使用編譯后的路徑
        JSONPath sizePath = JSONPath.of("$.store.book.size()");
        Integer size = (Integer) sizePath.eval(object);
    }
}

FastJSON JSONPath 修改操作

FastJSON 的 JSONPath 不僅可以讀取數(shù)據(jù),還支持修改數(shù)據(jù),這是它的一個(gè)強(qiáng)大特性。

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONPath;
import com.alibaba.fastjson2.JSONObject;

public class FastJsonPathModifyExample {

    @Test
    public void testJsonPathSet() {
        JSONObject object = JSON.parseObject(json);

        // 修改第一本書的價(jià)格
        JSONPath.set(object, "$.store.book[0].price", 99.99);

        // 修改自行車的顏色
        JSONPath.set(object, "$.store.bicycle.color", "blue");

        // 批量修改所有書籍價(jià)格
        JSONPath.set(object, "$.store.book[*].price", 15.88);

        // 修改包含 isbn 的書籍的 category
        JSONPath.set(object, "$.store.book[?(@.isbn)].category", "classic");

        // 添加新字段
        JSONPath.set(object, "$.store.book[0].publisher", "Tech Press");

        // 數(shù)組末尾添加元素(通過路徑獲取數(shù)組后操作)
        JSONArray bookArray = (JSONArray) JSONPath.eval(object, "$.store.book");
        bookArray.add(JSON.parseObject("{\"title\":\"New Book\",\"price\":9.99}"));

        // 刪除字段
        JSONPath.remove(object, "$.store.bicycle");

        System.out.println(JSON.toJSONString(object));
    }
}

FastJSON JSONPath 其他操作

// 獲取集合大小
Integer size = (Integer) JSONPath.eval(object, "$.store.book.size()");

// 獲取集合第一個(gè)
Object first = JSONPath.eval(object, "$.store.book.first()");

// 獲取集合最后一個(gè)
Object last = JSONPath.eval(object, "$.store.book.last()");

// 獲取屬性所有值
Collection values = (Collection) JSONPath.eval(object, "$.store.book.values()");

Jackson - JsonPointer / Jackson JsonPath

Jackson 原生支持 JsonPointer (RFC 6901),但不是完整的 JSONPath 實(shí)現(xiàn)。若要使用 JSONPath 功能,可以通過以下兩種方式:

方式一:使用 JsonPointer(原生支持)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.18.2</version>
</dependency>
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonPointer;

public class JacksonJsonPointerExample {

    private String json = "...";
    private ObjectMapper mapper = new ObjectMapper();

    @Test
    public void testJsonPointer() throws Exception {
        JsonNode root = mapper.readTree(json);

        // 使用 JsonPointer 定位節(jié)點(diǎn)
        JsonPointer ptr = JsonPointer.compile("/store/book/0/author");
        JsonNode authorNode = root.at(ptr);
        String author = authorNode.asText();

        // 鏈?zhǔn)綄懛?
        String title = root.at("/store/book/1/title").asText();
        Double price = root.at("/store/bicycle/price").asDouble();
    }
}

JsonPointer 限制

  • 語法較簡單,不支持通配符、過濾表達(dá)式
  • 無法一次獲取多個(gè)值
  • 不支持?jǐn)?shù)組切片

方式二:使用 Jackson-JsonPath(第三方擴(kuò)展)

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.9.0</version>
</dependency>
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;

public class JacksonJsonPathExample {

    // 配置使用 Jackson
    private Configuration configuration = Configuration.builder()
        .jsonProvider(new JacksonJsonNodeJsonProvider())
        .mappingProvider(new JacksonMappingProvider())
        .build();

    @Test
    public void testJacksonJsonPath() {
        List<String> authors = JsonPath.using(configuration)
            .parse(json)
            .read("$.store.book[*].author");
    }
}

Gson - 無原生 JSONPath

Gson 本身不提供 JSONPath 支持,這是 Gson 的一個(gè)局限。建議搭配 Jayway JsonPath 使用。

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.9.0</version>
</dependency>
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.jayway.jsonpath.JsonPath;

public class GsonJsonPathExample {

    private Gson gson = new Gson();
    private String json = "...";

    @Test
    public void testGsonWithJsonPath() {
        // 使用 JsonPath 提取數(shù)據(jù)
        List<String> authors = JsonPath.parse(json)
            .read("$.store.book[*].author");

        // 將結(jié)果轉(zhuǎn)回 Gson 對(duì)象
        JsonElement element = gson.toJsonTree(authors);
    }
}

三種方案對(duì)比

特性FastJSONJackson + JsonPointerJayway JsonPath
JSONPath 支持原生支持僅 JsonPointer完整支持
過濾表達(dá)式支持不支持支持
通配符支持不支持支持
性能優(yōu)秀優(yōu)秀良好
生態(tài)穩(wěn)定性曾有安全漏洞最穩(wěn)定社區(qū)活躍
Spring Boot 集成需手動(dòng)配置默認(rèn)集成需添加依賴

選型建議

  • 已有 FastJSON 項(xiàng)目:直接使用 FastJSON 的 JSONPath
  • 使用 Jackson 的項(xiàng)目:簡單場景用 JsonPointer,復(fù)雜場景引入 Jayway JsonPath
  • 使用 Gson 的項(xiàng)目:建議搭配 Jayway JsonPath 使用
  • 新項(xiàng)目:推薦 Jackson + Jayway JsonPath 組合

總結(jié)

JSONPath 是處理 JSON 數(shù)據(jù)的利器,通過簡潔的路徑表達(dá)式實(shí)現(xiàn)復(fù)雜字段提取、條件過濾和動(dòng)態(tài)查詢。在 Spring Boot 中集成 JSONPath 可大幅簡化代碼、提升可讀性,是處理復(fù)雜 JSON 結(jié)構(gòu)和第三方 API 數(shù)據(jù)的一種可選技術(shù)方案。

以上就是SpringBoot使用JSONPath實(shí)現(xiàn)高效處理JSON數(shù)據(jù)的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot處理JSON數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中LocalDate的詳細(xì)方法舉例總結(jié)

    Java中LocalDate的詳細(xì)方法舉例總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中LocalDate詳細(xì)方法舉例的相關(guān)資料,LocalDate主要是用來處理日期的類,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 基于Mybatis-plus實(shí)現(xiàn)多租戶架構(gòu)的全過程

    基于Mybatis-plus實(shí)現(xiàn)多租戶架構(gòu)的全過程

    多租戶是一種軟件架構(gòu)技術(shù),在多用戶的環(huán)境下,共有同一套系統(tǒng),并且要注意數(shù)據(jù)之間的隔離性,下面這篇文章主要給大家介紹了關(guān)于基于Mybatis-plus實(shí)現(xiàn)多租戶架構(gòu)的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Servlet簡單實(shí)現(xiàn)登錄功能

    Servlet簡單實(shí)現(xiàn)登錄功能

    這篇文章主要為大家詳細(xì)介紹了Servlet簡單實(shí)現(xiàn)登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Spring Boot設(shè)置并使用緩存的步驟

    Spring Boot設(shè)置并使用緩存的步驟

    今天小編就為大家分享一篇關(guān)于Spring Boot設(shè)置并使用緩存的步驟,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • java?web實(shí)現(xiàn)簡單登錄注冊功能全過程(eclipse,mysql)

    java?web實(shí)現(xiàn)簡單登錄注冊功能全過程(eclipse,mysql)

    前期我們學(xué)習(xí)了javaweb項(xiàng)目用JDBC連接數(shù)據(jù)庫,還有數(shù)據(jù)庫的建表功能,下面這篇文章主要給大家介紹了關(guān)于java?web實(shí)現(xiàn)簡單登錄注冊功能的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • Java中使用數(shù)組實(shí)現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實(shí)例

    Java中使用數(shù)組實(shí)現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實(shí)例

    這篇文章主要介紹了Java中使用數(shù)組實(shí)現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實(shí)例,本文先是講解了實(shí)現(xiàn)棧至少應(yīng)該包括以下幾個(gè)方法等知識(shí),然后給出代碼實(shí)例,需要的朋友可以參考下
    2015-01-01
  • CyclicBarrier之多線程中的循環(huán)柵欄詳解

    CyclicBarrier之多線程中的循環(huán)柵欄詳解

    這篇文章主要介紹了CyclicBarrier之多線程中的循環(huán)柵欄的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • 淺談Java8對(duì)字符串連接的改進(jìn)正確姿勢

    淺談Java8對(duì)字符串連接的改進(jìn)正確姿勢

    這篇文章主要介紹了Java8:對(duì)字符串連接的改進(jìn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • mybatisPlus中批量刪除的示例代碼

    mybatisPlus中批量刪除的示例代碼

    本文主要介紹了mybatisPlus中批量刪除的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java語言的11大特點(diǎn)(Java初學(xué)者必知)

    Java語言的11大特點(diǎn)(Java初學(xué)者必知)

    Java是一種簡單的,面向?qū)ο蟮模植际降?,解釋型的,健壯安全的,結(jié)構(gòu)中立的,可移植的,性能優(yōu)異、多線程的靜態(tài)語言。這篇文章主要介紹了Java語言的11大特點(diǎn),需要的朋友可以參考下
    2020-07-07

最新評(píng)論

大城县| 静宁县| 洛阳市| 天长市| 西盟| 贵溪市| 江陵县| 邵阳县| 六盘水市| 政和县| 雷州市| 广灵县| 游戏| 全州县| 克东县| 吴堡县| 山东省| 柳林县| 兴山县| 根河市| 四会市| 高雄市| 贡觉县| 遂昌县| 石屏县| 扬州市| 泰宁县| 新龙县| 塔城市| 榆林市| 铁岭县| 新沂市| 绍兴市| 罗城| 游戏| 临城县| 日土县| 台东县| 如东县| 宣化县| 鄂州市|