package utils;
import com.google.gson.*;
import java.lang.reflect.Array;
import java.util.Map;
/**
* 使用 gson 封装的操作 json 的工具类
*/
public final class EasyJson {
/**
* 全局的 Gson 转换对象
*/
private static final Gson gson = new Gson();
/**
* 通过父级对象实现树形结构
*/
private EasyJson parent;
/**
* 保存数据的对象
* 树形结构的节点,可以作为分支节点或者叶节点
*/
private JsonElement data;
private EasyJson(EasyJson parent, boolean isObj) {
this(parent, isObj ? new JsonObject() : new JsonArray());
}
private EasyJson(EasyJson parent, JsonElement data) {
this.data = data;
this.parent = parent;
}
/**
* 获取EasyJson实例
*
* @return 默认的 JsonObject
*/
public static EasyJson getInstance() {
return getInstance(null, Boolean.TRUE);
}
/**
* 获取EasyJson实例
*
* @param isObj 如果为true,构造实例为JsonObject,反之为JsonArray
*/
public static EasyJson getInstance(boolean isObj) {
return getInstance(null, isObj);
}
/**
* 获取EasyJson实例
*
* @param parent 上层实例
* @param isObj 是否构造为JsonObject
*/
public static EasyJson getInstance(EasyJson parent, boolean isObj) {
return new EasyJson(parent, isObj);
}
/**
* 获取EasyJson实例
*
* @param data 指定构造的Json数据
*/
public static EasyJson getInstance(JsonElement data) {
return getInstance(null, data);
}
/**
* 获取EasyJson实例
*
* @param parent 上层实例
* @param data 指定构造的Json数据
*/
public static EasyJson getInstance(EasyJson parent, JsonElement data) {
return new EasyJson(parent, data);
}
/**
* 创建下一层EasyJson对象,并将新建的对象返回
*
* @param name 新建的EasyJson对象在上级对象中的名称
* @return 返回新建节点的指针
*/
public EasyJson subObj(String name) {
EasyJson sub = getInstance(this, Boolean.TRUE);
this.put(name, sub.data);
return sub;
}
/**
* 基于当前 JsonArray 对象,创建下一层EasyJson对象
*
* @return 返回新建节点的指针
*/
public EasyJson subObj() {
EasyJson sub = getInstance(this, Boolean.TRUE);
this.add(sub.data);
return sub;
}
/**
* 构建新的 JsonArray 节点,并返回节点指针
*
* @param name 新建的EasyJson对象在上级对象中的名称
* @return 返回新建节点的指针
*/
public EasyJson subArr(String name) {
EasyJson sub = getInstance(this, Boolean.FALSE);
this.put(name, sub.data);
return sub;
}
/**
* 构建新的 JsonArray 节点,并返回节点指针
*
* @return 返回新建节点的指针
*/
public EasyJson subArr() {
EasyJson sub = getInstance(this, Boolean.FALSE);
this.add(sub.data);
return sub;
}
/**
* 结束子 EasyJson 对象的操作,返回上层对象
*
* @return 返回上层对象的指针
*/
public EasyJson endSub() {
return this.parent;
}
/**
* 构造上层对象,对象实例为 JsonObject
*
* @param name 当前对象在上层对象中的名称
* @return 返回上层对象的指针
*/
public EasyJson supObj(String name) {
EasyJson parent = getInstance(this, Boolean.TRUE);
parent.put(name, this.data);
this.parent = parent;
return parent;
}
/**
* 构造上层对象,对象实例为 JsonArray
*
* @return 返回上层对象的指针
*/
public EasyJson supArr() {
EasyJson parent = getInstance(this, Boolean.FALSE);
parent.add(this.data);
this.parent = parent;
return parent;
}
/**
* 给 JsonObject 对象添加键值对
* 请注意,如果属性中已有相同的键,那么旧值将会被覆盖为新值。
* 示例:put("add", "a").put("add", "b"); // json:{"add":"b"}
*
* @param name 键
* @param val 值
* @return 返回当前 EasyJson 对象
*/
public EasyJson put(String name, Object val) {
if (data instanceof JsonObject) {
((JsonObject) data).add(name, adapter(val));
} else {
throw new IllegalArgumentException("Must put for JsonObject.");
}
return this;
}
/**
* 给 JsonArray 对象添加值
*
* @param val 值
* @return 返回当前 EasyJson 对象
*/
public EasyJson add(Object val) {
if (data instanceof JsonArray) {
((JsonArray) data).add(adapter(val));
} else {
throw new IllegalArgumentException("Must put for JsonArray.");
}
return this;
}
/**
* 给 JsonArray 对象添加值
*
* @param val 类型必须是JsonArray,Array,Iterable
* @return 返回当前 EasyJson 对象
*/
public EasyJson addAll(Object val) {
if (data instanceof JsonArray) {
JsonArray jsonArray = adapter(val).getAsJsonArray();
((JsonArray) data).addAll(jsonArray);
} else {
throw new IllegalArgumentException("Must put for JsonArray.");
}
return this;
}
/**
* 将 Object 类型的数据构造为适配的 JsonElement 对象
* 当前支持的类型有:基本类型,string,Iterable,Map,JsonElement,EasyJson
*
* @param obj 数据
* @return 返回适配的 JsonElement 对象
* @throws IllegalArgumentException 如果参数是不支持类型,将会抛出该异常
*/
private static JsonElement adapter(Object obj) {
if (obj == null) {
return JsonNull.INSTANCE;
}
Class clazz = obj.getClass();
if (obj instanceof JsonElement) {
return (JsonElement) obj;
} else if (obj instanceof EasyJson) {
return ((EasyJson) obj).data;
} else if (obj instanceof String) {
return new JsonPrimitive((String) obj);
} else if (obj instanceof Number) {
return new JsonPrimitive((Number) obj);
} else if (obj instanceof Character) {
return new JsonPrimitive((Character) obj);
} else if (obj instanceof Boolean) {
return new JsonPrimitive((Boolean) obj);
} else if (obj instanceof Iterable) {
Iterable iterable = (Iterable) obj;
return adapterJsonArray(iterable);
} else if (clazz.isArray()) {
return adapterJsonArray(obj);
} else if (obj instanceof Map) {
Map map = (Map) obj;
return adapterJsonObject(map);
} else {
throw new IllegalArgumentException("Cannot adapter this classType:" + clazz.getName());
}
}
/**
* 将集合类型的数据适配为 JsonArray 对象
*
* @param iterable 数据
* @return 返回适配的 JsonArray 对象
*/
private static JsonArray adapterJsonArray(Iterable iterable) {
JsonArray arr = new JsonArray();
for (Object o : iterable) {
arr.add(adapter(o));
}
return arr;
}
/**
* 将数组类型的数据适配为 JsonArray 对象
*
* @param arr 数据
* @return 返回适配的 JsonArray 对象
* @throws IllegalArgumentException 如果参数不是数组类型,将会抛出该异常
*/
private static JsonArray adapterJsonArray(Object arr) {
JsonArray jsonArr = new JsonArray();
int length = Array.getLength(arr);
for (int i = 0; i < length; i++) {
JsonElement ele = adapter(Array.get(arr, i));
jsonArr.add(ele);
}
return jsonArr;
}
/**
* 将 Map 类型的数据适配为 JsonObject 对象
*
* @param map 数据
* @return 返回适配的 JsonObject 对象
* @throws IllegalArgumentException 如果 map 中含有值为 null 的键,将会抛出该异常
*/
private static JsonObject adapterJsonObject(Map map) {
JsonObject jsonObj = new JsonObject();
for (Object o : map.keySet()) {
if (o == null) {
throw new IllegalArgumentException("Map key cannot is null.");
}
String key = o.toString();
JsonElement val = adapter(map.get(key));
jsonObj.add(key, val);
}
return jsonObj;
}
@Override
public String toString() {
return gson.toJson(data);
}
public JsonElement getData() {
return this.data;
}
public static JsonObject getJsonObject(JsonElement data, String path) {
return (JsonObject) getPath(data, path);
}
public static JsonArray getJsonArray(JsonElement data, String path) {
return (JsonArray) getPath(data, path);
}
public static String getAsString(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsString();
}
public static char getAsChar(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsCharacter();
}
public static boolean getAsBoolean(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsBoolean();
}
public static long getAsLong(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsLong();
}
public static int getAsInt(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsInt();
}
public static double getAsDouble(JsonElement data, String path) {
return getJsonPrimitive(data, path).getAsDouble();
}
private static JsonPrimitive getJsonPrimitive(JsonElement data, String path) {
return (JsonPrimitive) getPath(data, path);
}
/**
* 根据路径获取 json 中对应的值。考虑到方便外部 JsonElement 对象的使用,设为静态方法
* 伪代码示例:
* JsonElement json = {"name": "frank", "language": ["Java", "GoLang"], "pet": {"clazz":"dog", "name":"BenBen"}}
* getPath(json, "language:1"); // JsonPrimitive("GoLang")
* getPath(json, "pet/name"); // JsonPrimitive("BenBen")
*
* @param data 为了调用方便,所以使用了JsonElement作为参数类型
* @param path name 以 / 分隔,如果是取JsonArray的值,在 name 后加上冒号和下标
* @return 返回 Json 中对应的值,如果节点中没有找到对应的值,将会返回null
* @throws ClassCastException 如果传入的 data 类型不是分支节点将会抛出类型转换异常
*/
private static JsonElement getPath(JsonElement data, String path) {
JsonElement ret = null;
if (data != null) {
JsonElement ele = data;
String[] split = path.split("/");
for (String component : split) {
if (ele == null) {
break;
}
if (component.contains(":")) {
String[] split2 = component.split(":");
ele = ((JsonObject) ele).get(split2[0]);
int index = Integer.parseInt(split2[1]);
ele = ((JsonArray) ele).get(index);
} else {
ele = ((JsonObject) ele).get(component);
}
}
ret = ele;
}
return ret;
}
}
测试代码:
@Test
public void testEasyJson() {
EasyJson easyJson = getInstance().put("name", "frank")
.subArr("language").add("Java").add("GoLang").endSub()
.subObj("pet").put("clazz", "dog").put("name", "BenBen").endSub();
System.out.println(getPath(easyJson.getData(), "language:1"));
System.out.println(getPath(easyJson.getData(), "pet/name"));
}
感谢参考博文:https://blog.youkuaiyun.com/axuanqq/article/details/51441590
end~