当前位置: 代码网 > it编程>编程语言>Java > java:json-path支持fastjson作为JSON解析提供者的技术实现方式

java:json-path支持fastjson作为JSON解析提供者的技术实现方式

2025年12月28日 Java 我要评论
1. 简介1.1 json-pathjson-path 是一个强大的json查询库,允许用户使用类似xpath的语法来查询json数据。它提供了灵活的api,可以在java应用中方便地处理json数据

1. 简介

1.1 json-path

json-path 是一个强大的json查询库,允许用户使用类似xpath的语法来查询json数据。

它提供了灵活的api,可以在java应用中方便地处理json数据。

1.2 fastjson

fastjson 是阿里巴巴开源的高性能json处理库,具有快速的序列化和反序列化能力,广泛应用于java项目中。

1.3 为什么需要让json-path支持fastjson?

json-path默认支持多种json解析库,如jackson、gson等,但不直接支持fastjson。

通过扩展json-path,使其支持fastjson,可以让项目在使用json-path的同时,继续享受fastjson的高性能优势。

2. 技术实现原理

2.1 核心接口

json-path通过以下两个核心接口来扩展json解析支持:

  1. jsonprovider:负责json解析和基本的json操作
  2. mappingprovider:负责json对象与java对象之间的映射

2.2 实现架构

我们的实现包括以下几个核心类:

类名作用实现方式
fastjsonjsonprovider实现jsonprovider接口扩展abstractjsonprovider
fastjsonmappingprovider实现mappingprovider接口直接实现接口
xjsonpathconfiguration自动检测和配置默认解析器静态初始化+自动检测

2.3 关键实现细节

2.3.1 fastjsonjsonprovider

fastjsonjsonprovider扩展了abstractjsonprovider,使用json.parsejson.parseobject实现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 实现 {@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实现了mappingprovider接口,使用fastjson的typeutils.cast方法简化实现:

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 实现 {@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);
        }
        // 统一使用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);
        }
        // 统一使用typeutils.cast解析
        return typeutils.cast(source, targettype.gettype(), parserconfig);
    }
}

2.3.3 xjsonpathconfiguration

xjsonpathconfiguration负责自动检测和配置默认解析器:

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配置扩展类<br>
 * 作为{@link configuration}的扩展<br>
 * 自动检测系统中可用的json解析库并设置默认配置<br>
 * 优先级为:fastjson > jackson > gson > jettison > org.json > tapestryjson
 */
public final class xjsonpathconfiguration {
    /**
     * 标记是否已经自动设置默认配置<br>
     * 防止重复初始化
     */
    private static boolean autoset = false;
    /**
     * 静态初始化块,在类加载时自动设置默认配置
     */
    static {
        autosetdefaults();
    }
    
    private xjsonpathconfiguration() {
        // 私有构造方法,防止实例化
    }

    /**
     * 自动检测并设置jsonpath默认配置<br>
     * 根据系统中可用的json解析库,优先级为:fastjson > jackson > gson > jettison > org.json > tapestryjson<br>
     * 该方法只会执行一次,后续调用将不再执行该方法
    */
    public static synchronized void autosetdefaults() {
        if (autoset) {
            return ;
        }
        autoset = true;
        configuration.defaults defaults = null;
        
        // 检测fastjson是否可用
        if (isfastjsonavailable()) {
            // 使用createdefaults方法创建fastjson的默认配置
            defaults = createdefaults(new fastjsonjsonprovider(), 
                                      new fastjsonmappingprovider());
        } else if (isjacksonavailable()) {
            // 使用jackson作为默认json解析库
            defaults = createdefaults("com.jayway.jsonpath.spi.json.jacksonjsonprovider", 
                                      "com.jayway.jsonpath.spi.mapper.jacksonmappingprovider");
        } else if (isgsonavailable()) {
            // 使用gson作为默认json解析库
            defaults = createdefaults("com.jayway.jsonpath.spi.json.gsonjsonprovider", 
                                      "com.jayway.jsonpath.spi.mapper.gsonmappingprovider");
        } else if (isjettisonavailable()) {
            // 使用jettison作为默认json解析库,mappingproviderclassname设为null,将使用默认的jsonsmartmappingprovider
            defaults = createdefaults("com.jayway.jsonpath.spi.json.jettisonprovider", null);
        } else if (isorgjsonavailable()) {
            // 使用org.json作为默认json解析库
            defaults = createdefaults("com.jayway.jsonpath.spi.json.jsonorgjsonprovider", 
                                      "com.jayway.jsonpath.spi.mapper.jsonorgmappingprovider");
        } else if (istapestryjsonavailable()) {
            // 使用tapestryjson作为默认json解析库
            defaults = createdefaults("com.jayway.jsonpath.spi.json.tapestryjsonprovider", 
                                      "com.jayway.jsonpath.spi.mapper.tapestrymappingprovider");
        }
        
        if (defaults != null) {
            configuration.setdefaults(defaults);
        }
    }

    /**
     * 获取默认配置,与{@link configuration#defaultconfiguration()}类似
     * 但会使用xjsonpathconfiguration自动检测到的json解析库
     * @return 默认配置实例
     */
    public static configuration defaultconfiguration() {
        // 静态初始化块已经自动设置了默认配置,直接返回configuration.defaultconfiguration()即可
        return configuration.defaultconfiguration();
    }

    /**
     * 根据类名创建json提供者和映射提供者的默认配置
     * @param jsonproviderclassname json提供者类名
     * @param mappingproviderclassname 映射提供者类名,可为null,为空则使用jsonsmartmappingprovider
     * @return configuration.defaults实例,如果创建失败返回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) {
                // 如果提供了映射提供者类名,通过反射实例化
                class<?> mappingproviderclass = class.forname(mappingproviderclassname);
                mappingprovider = (mappingprovider) mappingproviderclass.newinstance();
            } else {
                // 如果没有提供映射提供者类名,使用默认的jsonsmartmappingprovider
                mappingprovider = new jsonsmartmappingprovider();
            }
            return createdefaults(jsonprovider, mappingprovider);
        } catch (exception e) {
            // 如果实例化失败,返回null,继续检测下一个json解析库
            return null;
        }
    }
    /**
     * 根据json提供者和映射提供者创建默认配置
     * @param jsonprovider json提供者实例
     * @param mappingprovider 映射提供者实例,可为null,为空则使用jsonsmartmappingprovider
     * @return configuration.defaults实例,如果创建失败返回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 类名字符串数组
     * @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 自动检测机制

xjsonpathconfiguration实现了自动检测机制,可以根据系统中可用的json解析库自动选择最合适的解析器,优先级为:

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

3. json-path与fastjson内置jsonpath的区别

特性json-pathfastjson内置jsonpath
设计目标通用json查询库,支持多种解析器仅fastjson内部使用
语法类xpath语法,更丰富类xpath语法,相对简单
扩展性支持多种json解析器仅支持fastjson
功能更全面,支持复杂查询、映射等基础查询功能
性能取决于底层解析器与fastjson深度集成,性能可能更高
使用场景跨平台、需要灵活切换解析器仅使用fastjson的项目

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

4.1 现有项目已使用json-path,但希望使用fastjson提高性能

如果项目中已经大量使用了json-path,但对性能有更高要求,可以通过我们的实现无缝切换到底层使用fastjson,无需修改现有代码。

4.2 需要在不同环境下灵活切换json解析器

通过xjsonpathconfiguration的自动检测机制,可以在不同环境下自动选择可用的最佳解析器,提高项目的适应性和兼容性。

4.3 同时需要json-path的强大功能和fastjson的高性能

json-path提供了丰富的查询功能,而fastjson提供了高性能,结合两者可以在复杂json查询场景下获得更好的性能表现。

4.4 项目中已有fastjson依赖,不希望引入额外的json解析库

如果项目中已经使用了fastjson,可以通过我们的实现让json-path复用fastjson,避免引入额外的依赖,减小项目体积。

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
}

// 使用默认配置进行映射
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. 总结

通过实现fastjsonjsonproviderfastjsonmappingprovider,我们成功地让json-path支持了fastjson作为底层json解析库。这种实现方式具有以下优势:

  1. 高性能:利用fastjson的高性能特性,提高json-path的解析速度
  2. 灵活性:可以根据系统环境自动选择最佳解析器
  3. 兼容性:无需修改现有json-path代码,无缝集成
  4. 易用性:自动初始化,无需手动配置
  5. 扩展性:可以方便地支持更多json解析库

json-path支持fastjson为开发者提供了更多选择,可以根据项目需求灵活选择合适的json处理方案,在保持json-path强大功能的同时,享受fastjson的高性能优势。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

参考资料:

  1. json-path官方文档
  2. fastjson官方文档
  3. json-path api文档
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com