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

java:json-path支持fastjson作為JSON解析提供者的技術(shù)實(shí)現(xiàn)方式

 更新時間:2025年12月28日 10:09:14   作者:10km  
json-path和fastjson都是Java中常用的JSON處理庫,json-path支持多種解析器,而fastjson具有高性能,通過擴(kuò)展json-path,使其支持fastjson,可以在保持json-path強(qiáng)大功能的同時,享受fastjson的高性能優(yōu)勢

1. 簡介

1.1 json-path

json-path 是一個強(qiáng)大的JSON查詢庫,允許用戶使用類似XPath的語法來查詢JSON數(shù)據(jù)。

它提供了靈活的API,可以在Java應(yīng)用中方便地處理JSON數(shù)據(jù)。

1.2 fastjson

fastjson 是阿里巴巴開源的高性能JSON處理庫,具有快速的序列化和反序列化能力,廣泛應(yīng)用于Java項(xiàng)目中。

1.3 為什么需要讓json-path支持fastjson?

json-path默認(rèn)支持多種JSON解析庫,如jackson、gson等,但不直接支持fastjson。

通過擴(kuò)展json-path,使其支持fastjson,可以讓項(xiàng)目在使用json-path的同時,繼續(xù)享受fastjson的高性能優(yōu)勢。

2. 技術(shù)實(shí)現(xiàn)原理

2.1 核心接口

json-path通過以下兩個核心接口來擴(kuò)展JSON解析支持:

  1. JsonProvider:負(fù)責(zé)JSON解析和基本的JSON操作
  2. MappingProvider:負(fù)責(zé)JSON對象與Java對象之間的映射

2.2 實(shí)現(xiàn)架構(gòu)

我們的實(shí)現(xiàn)包括以下幾個核心類:

類名作用實(shí)現(xiàn)方式
FastjsonJsonProvider實(shí)現(xiàn)JsonProvider接口擴(kuò)展AbstractJsonProvider
FastjsonMappingProvider實(shí)現(xiàn)MappingProvider接口直接實(shí)現(xiàn)接口
XJsonPathConfiguration自動檢測和配置默認(rèn)解析器靜態(tài)初始化+自動檢測

2.3 關(guān)鍵實(shí)現(xiàn)細(xì)節(jié)

2.3.1 FastjsonJsonProvider

FastjsonJsonProvider擴(kuò)展了AbstractJsonProvider,使用JSON.parseJSON.parseObject實(shí)現(xiàn)JSON解析:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.google.common.base.MoreObjects;
import com.jayway.jsonpath.spi.json.AbstractJsonProvider;

import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * Fastjson 實(shí)現(xiàn) {@link com.jayway.jsonpath.spi.json.JsonProvider}
 */
public class FastjsonJsonProvider extends AbstractJsonProvider {
	private final ParserConfig parserConfig;
    public FastjsonJsonProvider() {
        this(null);
    }
    public FastjsonJsonProvider(ParserConfig parserConfig) {
        this.parserConfig = MoreObjects.firstNonNull(parserConfig, ParserConfig.getGlobalInstance());
    }
    @Override
    public Object parse(String json) {
        return JSON.parse(json, parserConfig);
    }

    @Override
    public Object parse(InputStream is, String charset) {
        try {
            return JSON.parseObject(is, Charset.forName(charset), JSON.class, parserConfig);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Object createMap() {
        return new JSONObject();
    }

    @Override
    public Object createArray() {
        return new JSONArray();
    }

    @Override
    public String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }
}

2.3.2 FastjsonMappingProvider

FastjsonMappingProvider實(shí)現(xiàn)了MappingProvider接口,使用fastjson的TypeUtils.cast方法簡化實(shí)現(xiàn):

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
import com.google.common.base.MoreObjects;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
import com.jayway.jsonpath.TypeRef;

/**
 * Fastjson 實(shí)現(xiàn) {@link MappingProvider}
 */
public class FastjsonMappingProvider implements MappingProvider {
    private final ParserConfig parserConfig;
    public FastjsonMappingProvider() {
        this(ParserConfig.getGlobalInstance());
    }
    public FastjsonMappingProvider(ParserConfig parserConfig) {
        this.parserConfig = MoreObjects.firstNonNull(parserConfig, ParserConfig.getGlobalInstance());
    }
    @Override
    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {
        if (targetType.isInstance(source)) {
            return targetType.cast(source);
        }
        if (source instanceof String) {
        	// 對于字符串,直接使用JSON.parseObject解析
            return JSON.parseObject((String) source, targetType, parserConfig);
        }
        // 統(tǒng)一使用TypeUtils.cast解析
        return TypeUtils.cast(source, targetType, parserConfig);
    }

    @Override
    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {
        if (source instanceof String) {
            // 對于字符串,直接使用JSON.parseObject解析
            return JSON.parseObject((String) source, targetType.getType(), parserConfig);
        }
        // 統(tǒng)一使用TypeUtils.cast解析
        return TypeUtils.cast(source, targetType.getType(), parserConfig);
    }
}

2.3.3 XJsonPathConfiguration

XJsonPathConfiguration負(fù)責(zé)自動檢測和配置默認(rèn)解析器:

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;

import java.util.Collections;
import java.util.Set;

/**
 * JsonPath配置擴(kuò)展類<br>
 * 作為{@link Configuration}的擴(kuò)展<br>
 * 自動檢測系統(tǒng)中可用的JSON解析庫并設(shè)置默認(rèn)配置<br>
 * 優(yōu)先級為:fastjson > jackson > gson > jettison > org.json > TapestryJson
 */
public final class XJsonPathConfiguration {
    /**
     * 標(biāo)記是否已經(jīng)自動設(shè)置默認(rèn)配置<br>
     * 防止重復(fù)初始化
     */
    private static boolean autoSet = false;
    /**
     * 靜態(tài)初始化塊,在類加載時自動設(shè)置默認(rèn)配置
     */
    static {
        autoSetDefaults();
    }
    
    private XJsonPathConfiguration() {
        // 私有構(gòu)造方法,防止實(shí)例化
    }

    /**
     * 自動檢測并設(shè)置JsonPath默認(rèn)配置<br>
     * 根據(jù)系統(tǒng)中可用的JSON解析庫,優(yōu)先級為:fastjson > jackson > gson > jettison > org.json > TapestryJson<br>
     * 該方法只會執(zhí)行一次,后續(xù)調(diào)用將不再執(zhí)行該方法
    */
    public static synchronized void autoSetDefaults() {
        if (autoSet) {
            return ;
        }
        autoSet = true;
        Configuration.Defaults defaults = null;
        
        // 檢測fastjson是否可用
        if (isFastjsonAvailable()) {
            // 使用createDefaults方法創(chuàng)建fastjson的默認(rèn)配置
            defaults = createDefaults(new FastjsonJsonProvider(), 
                                      new FastjsonMappingProvider());
        } else if (isJacksonAvailable()) {
            // 使用jackson作為默認(rèn)JSON解析庫
            defaults = createDefaults("com.jayway.jsonpath.spi.json.JacksonJsonProvider", 
                                      "com.jayway.jsonpath.spi.mapper.JacksonMappingProvider");
        } else if (isGsonAvailable()) {
            // 使用gson作為默認(rèn)JSON解析庫
            defaults = createDefaults("com.jayway.jsonpath.spi.json.GsonJsonProvider", 
                                      "com.jayway.jsonpath.spi.mapper.GsonMappingProvider");
        } else if (isJettisonAvailable()) {
            // 使用jettison作為默認(rèn)JSON解析庫,mappingProviderClassName設(shè)為null,將使用默認(rèn)的JsonSmartMappingProvider
            defaults = createDefaults("com.jayway.jsonpath.spi.json.JettisonProvider", null);
        } else if (isOrgJsonAvailable()) {
            // 使用org.json作為默認(rèn)JSON解析庫
            defaults = createDefaults("com.jayway.jsonpath.spi.json.JsonOrgJsonProvider", 
                                      "com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider");
        } else if (isTapestryJsonAvailable()) {
            // 使用TapestryJson作為默認(rèn)JSON解析庫
            defaults = createDefaults("com.jayway.jsonpath.spi.json.TapestryJsonProvider", 
                                      "com.jayway.jsonpath.spi.mapper.TapestryMappingProvider");
        }
        
        if (defaults != null) {
            Configuration.setDefaults(defaults);
        }
    }

    /**
     * 獲取默認(rèn)配置,與{@link Configuration#defaultConfiguration()}類似
     * 但會使用XJsonPathConfiguration自動檢測到的JSON解析庫
     * @return 默認(rèn)配置實(shí)例
     */
    public static Configuration defaultConfiguration() {
        // 靜態(tài)初始化塊已經(jīng)自動設(shè)置了默認(rèn)配置,直接返回Configuration.defaultConfiguration()即可
        return Configuration.defaultConfiguration();
    }

    /**
     * 根據(jù)類名創(chuàng)建JSON提供者和映射提供者的默認(rèn)配置
     * @param jsonProviderClassName JSON提供者類名
     * @param mappingProviderClassName 映射提供者類名,可為null,為空則使用JsonSmartMappingProvider
     * @return Configuration.Defaults實(shí)例,如果創(chuàng)建失敗返回null
     */
    private static Configuration.Defaults createDefaults(String jsonProviderClassName, String mappingProviderClassName) {
        try {
            Class<?> jsonProviderClass = Class.forName(jsonProviderClassName);
            final JsonProvider jsonProvider = (JsonProvider) jsonProviderClass.newInstance();
            final MappingProvider mappingProvider;
            if (mappingProviderClassName != null) {
                // 如果提供了映射提供者類名,通過反射實(shí)例化
                Class<?> mappingProviderClass = Class.forName(mappingProviderClassName);
                mappingProvider = (MappingProvider) mappingProviderClass.newInstance();
            } else {
                // 如果沒有提供映射提供者類名,使用默認(rèn)的JsonSmartMappingProvider
                mappingProvider = new JsonSmartMappingProvider();
            }
            return createDefaults(jsonProvider, mappingProvider);
        } catch (Exception e) {
            // 如果實(shí)例化失敗,返回null,繼續(xù)檢測下一個JSON解析庫
            return null;
        }
    }
    /**
     * 根據(jù)JSON提供者和映射提供者創(chuàng)建默認(rèn)配置
     * @param jsonProvider JSON提供者實(shí)例
     * @param mappingProvider 映射提供者實(shí)例,可為null,為空則使用JsonSmartMappingProvider
     * @return Configuration.Defaults實(shí)例,如果創(chuàng)建失敗返回null
     */
    private static Configuration.Defaults createDefaults(final JsonProvider jsonProvider, MappingProvider mappingProvider) {
    	final MappingProvider _mappingProvider = mappingProvider == null ? new JsonSmartMappingProvider() :mappingProvider;
    	return new Configuration.Defaults() {
    		@Override
    		public JsonProvider jsonProvider() {
    			return jsonProvider;
    		}
    		
    		@Override
    		public MappingProvider mappingProvider() {
    			return _mappingProvider;
    		}
    		
    		@Override
    		public Set<Option> options() {
    			return Collections.emptySet();
    		}
    	};
    }

    /**
     * 檢測多個類是否都可用
     * @param classNames 類名字符串?dāng)?shù)組
     * @return true if all classes are available, otherwise false
     */
    private static boolean isClassesAvailable(String... classNames) {
        try {
            for (String className : classNames) {
                Class.forName(className);
            }
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    /**
     * 檢測fastjson是否可用
     * @return true if fastjson is available
     */
    private static boolean isFastjsonAvailable() {
        return isClassesAvailable(
                "com.alibaba.fastjson.JSON",
                "com.alibaba.fastjson.JSONObject"
        );
    }

    /**
     * 檢測jackson是否可用
     * @return true if jackson is available
     */
    private static boolean isJacksonAvailable() {
        return isClassesAvailable(
                "com.fasterxml.jackson.databind.ObjectMapper",
                "com.jayway.jsonpath.spi.json.JacksonJsonProvider",
                "com.jayway.jsonpath.spi.mapper.JacksonMappingProvider"
        );
    }

    /**
     * 檢測gson是否可用
     * @return true if gson is available
     */
    private static boolean isGsonAvailable() {
        return isClassesAvailable(
                "com.google.gson.Gson",
                "com.jayway.jsonpath.spi.json.GsonJsonProvider",
                "com.jayway.jsonpath.spi.mapper.GsonMappingProvider"
        );
    }
    
    /**
     * 檢測jettison是否可用
     * @return true if jettison is available
     */
    private static boolean isJettisonAvailable() {
        return isClassesAvailable(
                "org.codehaus.jettison.json.JSONObject",
                "com.jayway.jsonpath.spi.json.JettisonProvider"
        );
    }
    
    /**
     * 檢測org.json是否可用
     * @return true if org.json is available
     */
    private static boolean isOrgJsonAvailable() {
        return isClassesAvailable(
                "org.json.JSONObject",
                "com.jayway.jsonpath.spi.json.JsonOrgJsonProvider"
        );
    }
    
    /**
     * 檢測TapestryJson是否可用
     * @return true if TapestryJson is available
     */
    private static boolean isTapestryJsonAvailable() {
        return isClassesAvailable(
                "org.apache.tapestry5.json.JSONObject",
                "com.jayway.jsonpath.spi.json.TapestryJsonProvider"
        );
    }
}

2.4 自動檢測機(jī)制

XJsonPathConfiguration實(shí)現(xiàn)了自動檢測機(jī)制,可以根據(jù)系統(tǒng)中可用的JSON解析庫自動選擇最合適的解析器,優(yōu)先級為:

fastjson > jackson > gson > jettison > org.json > TapestryJson

3. json-path與fastjson內(nèi)置JsonPath的區(qū)別

特性json-pathfastjson內(nèi)置JsonPath
設(shè)計目標(biāo)通用JSON查詢庫,支持多種解析器僅fastjson內(nèi)部使用
語法類XPath語法,更豐富類XPath語法,相對簡單
擴(kuò)展性支持多種JSON解析器僅支持fastjson
功能更全面,支持復(fù)雜查詢、映射等基礎(chǔ)查詢功能
性能取決于底層解析器與fastjson深度集成,性能可能更高
使用場景跨平臺、需要靈活切換解析器僅使用fastjson的項(xiàng)目

4. json-path支持fastjson的使用場景

4.1 現(xiàn)有項(xiàng)目已使用json-path,但希望使用fastjson提高性能

如果項(xiàng)目中已經(jīng)大量使用了json-path,但對性能有更高要求,可以通過我們的實(shí)現(xiàn)無縫切換到底層使用fastjson,無需修改現(xiàn)有代碼。

4.2 需要在不同環(huán)境下靈活切換JSON解析器

通過XJsonPathConfiguration的自動檢測機(jī)制,可以在不同環(huán)境下自動選擇可用的最佳解析器,提高項(xiàng)目的適應(yīng)性和兼容性。

4.3 同時需要json-path的強(qiáng)大功能和fastjson的高性能

json-path提供了豐富的查詢功能,而fastjson提供了高性能,結(jié)合兩者可以在復(fù)雜JSON查詢場景下獲得更好的性能表現(xiàn)。

4.4 項(xiàng)目中已有fastjson依賴,不希望引入額外的JSON解析庫

如果項(xiàng)目中已經(jīng)使用了fastjson,可以通過我們的實(shí)現(xiàn)讓json-path復(fù)用fastjson,避免引入額外的依賴,減小項(xiàng)目體積。

5. 使用示例

5.1 基本使用

import net.facelib.cell.json.XJsonPathConfiguration;
// 自動初始化,無需手動配置
XJsonPathConfiguration.autoSetDefaults();
// 直接使用json-path API
String json = "{\"name\":\"test\",\"age\":20}";
String name = JsonPath.read(json, "$.name");
System.out.println(name); // 輸出: test

5.2 對象映射

import net.facelib.cell.json.XJsonPathConfiguration;
// 自動初始化,無需手動配置
XJsonPathConfiguration.autoSetDefaults();
// 定義User類
class User {
    private String name;
    private int age;
    // getter/setter
}

// 使用默認(rèn)配置進(jìn)行映射
String json = "{\"name\":\"test\",\"age\":20}";
User user = JsonPath.parse(json).read("$", User.class);
System.out.println(user.getName()); // 輸出: test

5.3 泛型映射

import net.facelib.cell.json.XJsonPathConfiguration;
// 自動初始化,無需手動配置
XJsonPathConfiguration.autoSetDefaults();
// List泛型映射
String listJson = "[{\"name\":\"user1\",\"age\":20},{\"name\":\"user2\",\"age\":30}]";
List<User> userList = JsonPath.parse(listJson).read("$", new TypeRef<List<User>>() {});
System.out.println(userList.size()); // 輸出: 2

// Map泛型映射
String mapJson = "{\"user1\":{\"name\":\"user1\",\"age\":20},\"user2\":{\"name\":\"user2\",\"age\":30}}";
Map<String, User> userMap = JsonPath.parse(mapJson).read("$", new TypeRef<Map<String, User>>() {});
System.out.println(userMap.size()); // 輸出: 2

6. 總結(jié)

通過實(shí)現(xiàn)FastjsonJsonProviderFastjsonMappingProvider,我們成功地讓json-path支持了fastjson作為底層JSON解析庫。這種實(shí)現(xiàn)方式具有以下優(yōu)勢:

  1. 高性能:利用fastjson的高性能特性,提高json-path的解析速度
  2. 靈活性:可以根據(jù)系統(tǒng)環(huán)境自動選擇最佳解析器
  3. 兼容性:無需修改現(xiàn)有json-path代碼,無縫集成
  4. 易用性:自動初始化,無需手動配置
  5. 擴(kuò)展性:可以方便地支持更多JSON解析庫

json-path支持fastjson為開發(fā)者提供了更多選擇,可以根據(jù)項(xiàng)目需求靈活選擇合適的JSON處理方案,在保持json-path強(qiáng)大功能的同時,享受fastjson的高性能優(yōu)勢。

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

參考資料:

  1. json-path官方文檔
  2. fastjson官方文檔
  3. json-path API文檔

相關(guān)文章

  • Java多線程的用法詳細(xì)介紹

    Java多線程的用法詳細(xì)介紹

    這篇文章主要介紹了Java多線程的用法詳細(xì)介紹的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Spring事務(wù)管理中關(guān)于數(shù)據(jù)庫連接池詳解

    Spring事務(wù)管理中關(guān)于數(shù)據(jù)庫連接池詳解

    事務(wù)的作用就是為了保證用戶的每一個操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們在使用Spring Boot開發(fā)應(yīng)用時,大部分情況下也都需要使用事務(wù)
    2022-12-12
  • Java工具之ja-netfilter?2022.1?配置教程

    Java工具之ja-netfilter?2022.1?配置教程

    這篇文章主要介紹了Java工具之ja-netfilter?2022.1?配置教程,本防火墻基于javaagent,所以目前只有基于java的程序能夠使用,需要的朋友可以參考下
    2022-04-04
  • java實(shí)現(xiàn)學(xué)生宿舍系統(tǒng)

    java實(shí)現(xiàn)學(xué)生宿舍系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生宿舍系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 淺談Strut2如何對請求參數(shù)的封裝

    淺談Strut2如何對請求參數(shù)的封裝

    這篇文章主要介紹了淺談Strut2如何對請求參數(shù)的封裝,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • SpringCloud-Hystrix-Dashboard客戶端服務(wù)監(jiān)控的實(shí)現(xiàn)方法

    SpringCloud-Hystrix-Dashboard客戶端服務(wù)監(jiān)控的實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringCloud-Hystrix-Dashboard客戶端服務(wù)監(jiān)控的實(shí)現(xiàn)方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot Redis實(shí)現(xiàn)接口冪等性校驗(yàn)方法詳細(xì)講解

    SpringBoot Redis實(shí)現(xiàn)接口冪等性校驗(yàn)方法詳細(xì)講解

    這篇文章主要介紹了SpringBoot Redis實(shí)現(xiàn)接口冪等性校驗(yàn)方法,近期一個老項(xiàng)目出現(xiàn)了接口冪等性校驗(yàn)問題,前端加了按鈕置灰,依然被人拉著接口參數(shù)一頓輸出,還是重復(fù)調(diào)用了接口,通過復(fù)制粘貼,完成了后端接口冪等性調(diào)用校驗(yàn)
    2022-11-11
  • Java編程中使用lambda表達(dá)式的奇技淫巧

    Java編程中使用lambda表達(dá)式的奇技淫巧

    這篇文章主要介紹了Java編程中使用lambda表達(dá)式的奇技淫巧,使用Lambda表達(dá)式可以替代只有一個函數(shù)的接口實(shí)現(xiàn),告別匿名內(nèi)部類,代碼看起來更簡潔易懂,是Java8開始推出的人們期待已久的功能,需要的朋友可以參考下
    2016-03-03
  • SpringBoot Swagger2 接口規(guī)范示例詳解

    SpringBoot Swagger2 接口規(guī)范示例詳解

    Swagger(在谷歌、IBM、微軟等公司的支持下)做了一個公共的文檔風(fēng)格來填補(bǔ)上述問題,在本文中,我們將會學(xué)習(xí)怎么使用Swagger的 Swagger2注解去生成REST API文檔,感興趣的朋友一起看看吧
    2023-12-12
  • 使用springboot結(jié)合vue實(shí)現(xiàn)sso單點(diǎn)登錄

    使用springboot結(jié)合vue實(shí)現(xiàn)sso單點(diǎn)登錄

    這篇文章主要為大家詳細(xì)介紹了如何使用springboot+vue實(shí)現(xiàn)sso單點(diǎn)登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06

最新評論

聊城市| 台北县| 乌兰县| 启东市| 延津县| 兴海县| 平武县| 东安县| 扎鲁特旗| 东丰县| 漾濞| 武胜县| 灵石县| 罗江县| 交城县| 象州县| 柘荣县| 长岭县| 文昌市| 同心县| 苏尼特右旗| 桐庐县| 永川市| 达日县| 克山县| 京山县| 夏津县| 汝阳县| 龙南县| 扎囊县| 昌吉市| 玉树县| 治多县| 托克逊县| 衡阳市| 兴文县| 鸡泽县| 保德县| 如皋市| 本溪| 吐鲁番市|