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解析支持:
- JsonProvider:负责JSON解析和基本的JSON操作
- MappingProvider:负责JSON对象与Java对象之间的映射
2.2 实现架构
我们的实现包括以下几个核心类:
| 类名 | 作用 | 实现方式 |
|---|---|---|
FastjsonJsonProvider | 实现JsonProvider接口 | 扩展AbstractJsonProvider |
FastjsonMappingProvider | 实现MappingProvider接口 | 直接实现接口 |
XJsonPathConfiguration | 自动检测和配置默认解析器 | 静态初始化+自动检测 |
2.3 关键实现细节
2.3.1 FastjsonJsonProvider
FastjsonJsonProvider扩展了AbstractJsonProvider,使用JSON.parse和JSON.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-path | fastjson内置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. 总结
通过实现FastjsonJsonProvider和FastjsonMappingProvider,我们成功地让json-path支持了fastjson作为底层JSON解析库。这种实现方式具有以下优势:
- 高性能:利用fastjson的高性能特性,提高json-path的解析速度
- 灵活性:可以根据系统环境自动选择最佳解析器
- 兼容性:无需修改现有json-path代码,无缝集成
- 易用性:自动初始化,无需手动配置
- 扩展性:可以方便地支持更多JSON解析库
json-path支持fastjson为开发者提供了更多选择,可以根据项目需求灵活选择合适的JSON处理方案,在保持json-path强大功能的同时,享受fastjson的高性能优势。
1790

被折叠的 条评论
为什么被折叠?



