码字不易,请大佬们点点关注,谢谢~
一、JsonTreeBasedAdapter概述
1.1 在Gson中的角色定位
JsonTreeBasedAdapter是Gson库中用于实现基于JSON树模型(JsonElement)的序列化和反序列化的适配器。它作为TypeAdapter的一种具体实现,为那些需要灵活处理JSON结构的场景提供了强大支持。
与直接操作JsonReader和JsonWriter的TypeAdapter不同,JsonTreeBasedAdapter通过将JSON数据转换为中间的树模型(由JsonElement及其子类组成),再进行处理。这种方式虽然在性能上可能略逊一筹,但提供了更高的灵活性,尤其适合处理结构复杂或动态变化的JSON数据。
1.2 与其他适配器的关系
Gson中的适配器体系主要包括以下几种类型:
- 直接操作流的适配器:直接通过JsonReader和JsonWriter读写JSON数据,性能最优。
- 基于JsonTree的适配器:将JSON转换为树模型处理,提供更高的灵活性。
- 反射式适配器:通过Java反射自动处理普通Java对象。
JsonTreeBasedAdapter属于第二类,它在内部使用JsonSerializer和JsonDeserializer来处理JSON树模型:
// JsonTreeBasedAdapter类的定义
public final class JsonTreeBasedAdapter<T> extends TypeAdapter<T> {
private final JsonSerializer<T> serializer; // JSON序列化器
private final JsonDeserializer<T> deserializer; // JSON反序列化器
private final Gson gson; // Gson实例
private final TypeToken<T> typeToken; // 类型令牌
// 构造函数
public JsonTreeBasedAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
Gson gson, TypeToken<T> typeToken) {
this.serializer = serializer;
this.deserializer = deserializer;
this.gson = gson;
this.typeToken = typeToken;
}
// 实现TypeAdapter的write方法
@Override public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
// 使用JsonSerializer将对象转换为JsonElement
JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext());
// 将JsonElement写入JsonWriter
Streams.write(tree, out);
}
// 实现TypeAdapter的read方法
@Override public T read(JsonReader in) throws IOException {
// 从JsonReader读取并解析为JsonElement
JsonElement tree = Streams.parse(in);
if (tree.isJsonNull()) {
return null;
}
// 使用JsonDeserializer将JsonElement转换为对象
return deserializer.deserialize(tree, typeToken.getType(), gson.deserializationContext());
}
}
1.3 适用场景
JsonTreeBasedAdapter适用于以下场景:
- 动态JSON结构:当JSON结构不固定,需要在运行时动态处理时。
- 复杂转换逻辑:当序列化或反序列化逻辑复杂,需要完整的JSON树结构支持时。
- 与现有代码集成:当需要与使用JsonElement API的现有代码集成时。
- 自定义注解处理:当需要根据自定义注解调整序列化或反序列化行为时。
二、JSON树模型核心类结构
2.1 JsonElement层次结构
Gson的JSON树模型由JsonElement抽象类及其子类组成,主要包括:
- JsonPrimitive:表示基本类型值(字符串、数字、布尔值等)
- JsonArray:表示JSON数组
- JsonObject:表示JSON对象
- JsonNull:表示JSON null值
这些类的关系如下:
// JsonElement抽象类
public abstract class JsonElement implements Cloneable {
// 判断是否为JsonPrimitive
public boolean isJsonPrimitive() {
return this instanceof JsonPrimitive;
}
// 判断是否为JsonArray
public boolean isJsonArray() {
return this instanceof JsonArray;
}
// 判断是否为JsonObject
public boolean isJsonObject() {
return this instanceof JsonObject;
}
// 判断是否为JsonNull
public boolean isJsonNull() {
return this instanceof JsonNull;
}
// 转换为JsonPrimitive
public JsonPrimitive getAsJsonPrimitive() {
return (JsonPrimitive) this;
}
// 转换为JsonArray
public JsonArray getAsJsonArray() {
return (JsonArray) this;
}
// 转换为JsonObject
public JsonObject getAsJsonObject() {
return (JsonObject) this;
}
// 其他方法...
}
// JsonPrimitive类
public final class JsonPrimitive extends JsonElement {
private final Object value; // 存储基本类型值
// 构造函数
public JsonPrimitive(Boolean value) {
this.value = Preconditions.checkNotNull(value);
}
public JsonPrimitive(Number value) {
this.value = Preconditions.checkNotNull(value);
}
public JsonPrimitive(String value) {
this.value = Preconditions.checkNotNull(value);
}
// 获取各种类型的值
public boolean getAsBoolean() {
if (isBoolean()) {
return ((Boolean) value).booleanValue();
}
// 其他类型转换逻辑...
}
public Number getAsNumber() {
if (isNumber()) {
return (Number) value;
}
// 其他类型转换逻辑...
}
public String getAsString() {
if (isString()) {
return (String) value;
}
// 其他类型转换逻辑...
}
// 其他方法...
}
// JsonArray类
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
private final List<JsonElement> elements; // 存储数组元素
// 构造函数
public JsonArray() {
this.elements = new ArrayList<>();
}
// 添加元素
public void add(JsonElement element) {
elements.add(element == null ? JsonNull.INSTANCE : element);
}
// 获取元素
public JsonElement get(int index) {
return elements.get(index);
}
// 获取元素数量
public int size() {
return elements.size();
}
// 实现Iterable接口
@Override
public Iterator<JsonElement> iterator() {
return elements.iterator();
}
// 其他方法...
}
// JsonObject类
public final class JsonObject extends JsonElement {
private final LinkedTreeMap<String, JsonElement> members; // 存储对象成员
// 构造函数
public JsonObject() {
this.members = new LinkedTreeMap<>();
}
// 添加成员
public void add(String property, JsonElement value) {
if (value == null) {
value = JsonNull.INSTANCE;
}
members.put(property, value);
}
// 获取成员
public JsonElement get(String property) {
return members.get(property);
}
// 获取所有成员名
public Set<String> keySet() {
return members.keySet();
}
// 获取所有成员
public Set<Map.Entry<String, JsonElement>> entrySet() {
return members.entrySet();
}
// 其他方法...
}
// JsonNull类
public final class JsonNull extends JsonElement {
// 单例实现
public static final JsonNull INSTANCE = new JsonNull();
private JsonNull() {}
@Override
public int hashCode() {
return JsonNull.class.hashCode();
}
@Override
public boolean equals(Object obj) {
return this == obj || obj instanceof JsonNull;
}
}
2.2 JsonSerializer接口
JsonSerializer接口用于将Java对象序列化为JsonElement:
public interface JsonSerializer<T> {
/**
* 将Java对象序列化为JsonElement
*
* @param src 待序列化的对象
* @param typeOfSrc 对象的类型
* @param context 序列化上下文,可用于序列化对象的字段
* @return 序列化后的JsonElement
*/
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
}
2.3 JsonDeserializer接口
JsonDeserializer接口用于将JsonElement反序列化为Java对象:
public interface JsonDeserializer<T> {
/**
* 将JsonElement反序列化为Java对象
*
* @param json 待反序列化的JsonElement
* @param typeOfT 对象的类型
* @param context 反序列化上下文,可用于反序列化对象的字段
* @return 反序列化后的Java对象
* @throws JsonParseException 如果解析失败
*/
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException;
}
三、JsonTreeBasedAdapter源码解析
3.1 类定义与成员变量
public final class JsonTreeBasedAdapter<T> extends TypeAdapter<T> {
private final JsonSerializer<T> serializer; // JSON序列化器
private final JsonDeserializer<T> deserializer; // JSON反序列化器
private final Gson gson; // Gson实例
private final TypeToken<T> typeToken; // 类型令牌
// 构造函数
public JsonTreeBasedAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
Gson gson, TypeToken<T> typeToken) {
this.serializer = serializer;
this.deserializer = deserializer;
this.gson = gson;
this.typeToken = typeToken;
}
}
3.2 序列化流程
JsonTreeBasedAdapter的序列化流程通过write方法实现:
@Override public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue(); // 如果值为null,直接写入null
return;
}
// 使用JsonSerializer将对象转换为JsonElement
JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext());
// 将JsonElement写入JsonWriter
Streams.write(tree, out);
}
其中,Streams.write方法的实现如下:
public final class Streams {
/**
* 将JsonElement写入JsonWriter
*/
public static void write(JsonElement element, JsonWriter writer) throws IOException {
// 处理null值
if (element.isJsonNull()) {
writer.nullValue();
return;
}
// 处理布尔值
if (element.isJsonPrimitive()) {
JsonPrimitive primitive = element.getAsJsonPrimitive();
if (primitive.isBoolean()) {
writer.value(primitive.getAsBoolean());
return;
}
// 处理数字
if (primitive.isNumber()) {
writer.value(primitive.getAsNumber());
return;
}
// 处理字符串
if (primitive.isString()) {
writer.value(primitive.getAsString());
return;
}
throw new AssertionError();
}
// 处理数组
if (element.isJsonArray()) {
writer.beginArray();
for (JsonElement e : element.getAsJsonArray()) {
write(e, writer);
}
writer.endArray();
return;
}
// 处理对象
if (element.isJsonObject()) {
writer.beginObject();
for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) {
writer.name(entry.getKey());
write(entry.getValue(), writer);
}
writer.endObject();
return;
}
throw new AssertionError();
}
}
3.3 反序列化流程
JsonTreeBasedAdapter的反序列化流程通过read方法实现:
@Override public T read(JsonReader in) throws IOException {
// 从JsonReader读取并解析为JsonElement
JsonElement tree = Streams.parse(in);
if (tree.isJsonNull()) {
return null; // 如果是null值,直接返回null
}
// 使用JsonDeserializer将JsonElement转换为对象
return deserializer.deserialize(tree, typeToken.getType(), gson.deserializationContext());
}
其中,Streams.parse方法的实现如下:
public final class Streams {
/**
* 从JsonReader解析出JsonElement
*/
public static JsonElement parse(JsonReader reader) throws JsonParseException {
boolean isEmpty = true;
try {
reader.peek();
isEmpty = false;
return parse(reader, false);
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for empty
* documents instead of throwing.
*/
if (isEmpty) {
return JsonNull.INSTANCE;
}
// The stream ended prematurely so it is likely a syntax error.
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
private static JsonElement parse(JsonReader reader, boolean lenient) throws IOException {
JsonToken token = reader.peek();
switch (token) {
case BEGIN_ARRAY:
return parseArray(reader, lenient);
case BEGIN_OBJECT:
return parseObject(reader, lenient);
case STRING:
return new JsonPrimitive(reader.nextString());
case NUMBER:
String number = reader.nextString();
// 尝试将数字解析为合适的类型
try {
return new JsonPrimitive(Long.parseLong(number));
} catch (NumberFormatException e) {
try {
return new JsonPrimitive(Double.parseDouble(number));
} catch (NumberFormatException e2) {
return new JsonPrimitive(number);
}
}
case BOOLEAN:
return new JsonPrimitive(reader.nextBoolean());
case NULL:
reader.nextNull();
return JsonNull.INSTANCE;
case END_DOCUMENT:
case NAME:
case END_OBJECT:
case END_ARRAY:
throw new JsonSyntaxException("Unexpected token: " + token);
default:
throw new AssertionError();
}
}
// 解析JSON数组
private static JsonArray parseArray(JsonReader reader, boolean lenient) throws IOException {
JsonArray array = new JsonArray();
reader.beginArray();
while (reader.hasNext()) {
array.add(parse(reader, lenient));
}
reader.endArray();
return array;
}
// 解析JSON对象
private static JsonObject parseObject(JsonReader reader, boolean lenient) throws IOException {
JsonObject object = new JsonObject();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
object.add(name, parse(reader, lenient));
}
reader.endObject();
return object;
}
}
四、JsonSerializationContext与JsonDeserializationContext
4.1 序列化上下文
JsonSerializationContext接口提供了在序列化过程中处理对象字段的能力:
public interface JsonSerializationContext {
/**
* 将对象序列化为JsonElement
*
* @param src 待序列化的对象
* @return 序列化后的JsonElement
*/
public JsonElement serialize(Object src);
/**
* 将对象序列化为JsonElement,指定类型
*
* @param src 待序列化的对象
* @param typeOfSrc 对象的类型
* @return 序列化后的JsonElement
*/
public JsonElement serialize(Object src, Type typeOfSrc);
}
Gson中的默认实现类是SerializationContext:
final class SerializationContext implements JsonSerializationContext {
private final Gson gson;
SerializationContext(Gson gson) {
this.gson = gson;
}
@Override
public JsonElement serialize(Object src) {
if (src == null) {
return JsonNull.INSTANCE;
}
// 获取对象的实际类型
Type type = $Gson$Types.getRawType(src.getClass());
// 委托给Gson的toJsonTree方法
return gson.toJsonTree(src, type);
}
@Override
public JsonElement serialize(Object src, Type typeOfSrc) {
if (src == null) {
return JsonNull.INSTANCE;
}
// 委托给Gson的toJsonTree方法
return gson.toJsonTree(src, typeOfSrc);
}
}
4.2 反序列化上下文
JsonDeserializationContext接口提供了在反序列化过程中处理对象字段的能力:
public interface JsonDeserializationContext {
/**
* 将JsonElement反序列化为指定类型的对象
*
* @param json 待反序列化的JsonElement
* @param typeOfT 对象的类型
* @return 反序列化后的对象
* @throws JsonParseException 如果解析失败
*/
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
}
Gson中的默认实现类是DeserializationContext:
final class DeserializationContext implements JsonDeserializationContext {
private final Gson gson;
private final Stack<Type> stack;
DeserializationContext(Gson gson, Stack<Type> stack) {
this.gson = gson;
this.stack = stack;
}
@Override
@SuppressWarnings("unchecked")
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
if (json == null) {
return null;
}
// 检查循环引用
if (stack.contains(typeOfT)) {
throw new JsonParseException("Circular reference detected");
}
try {
// 将当前类型压入栈中
stack.push(typeOfT);
// 委托给Gson的fromJsonTree方法
return (T) gson.fromJsonTree(json, typeOfT);
} finally {
// 从栈中弹出当前类型
stack.pop();
}
}
}
五、实际应用案例
5.1 处理动态JSON结构
假设我们需要处理一个动态的JSON结构,其中某个字段的类型可能是字符串或对象:
{
"name": "John",
"data": "simple value"
}
或
{
"name": "Jane",
"data": {
"key1": "value1",
"key2": "value2"
}
}
我们可以使用JsonTreeBasedAdapter来处理这种情况:
class DynamicDataAdapter implements JsonDeserializer<Object>, JsonSerializer<Object> {
@Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.isJsonPrimitive()) {
// 如果是基本类型,直接返回字符串值
return json.getAsString();
} else if (json.isJsonObject()) {
// 如果是对象,转换为Map
Map<String, Object> map = new LinkedHashMap<>();
JsonObject jsonObject = json.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
// 递归处理每个字段
map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));
}
return map;
} else if (json.isJsonArray()) {
// 如果是数组,转换为List
List<Object> list = new ArrayList<>();
JsonArray jsonArray = json.getAsJsonArray();
for (JsonElement element : jsonArray) {
// 递归处理每个元素
list.add(context.deserialize(element, Object.class));
}
return list;
} else {
return null;
}
}
@Override
public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
if (src instanceof String) {
return new JsonPrimitive((String) src);
} else if (src instanceof Number) {
return new JsonPrimitive((Number) src);
} else if (src instanceof Boolean) {
return new JsonPrimitive((Boolean) src);
} else if (src instanceof Map) {
// 处理Map
JsonObject jsonObject = new JsonObject();
Map<?, ?> map = (Map<?, ?>) src;
for (Map.Entry<?, ?> entry : map.entrySet()) {
// 递归处理每个键值对
String key = String.valueOf(entry.getKey());
jsonObject.add(key, context.serialize(entry.getValue()));
}
return jsonObject;
} else if (src instanceof Collection) {
// 处理Collection
JsonArray jsonArray = new JsonArray();
Collection<?> collection = (Collection<?>) src;
for (Object element : collection) {
// 递归处理每个元素
jsonArray.add(context.serialize(element));
}
return jsonArray;
} else if (src.getClass().isArray()) {
// 处理数组
JsonArray jsonArray = new JsonArray();
int length = java.lang.reflect.Array.getLength(src);
for (int i = 0; i < length; i++) {
// 递归处理每个元素
jsonArray.add(context.serialize(java.lang.reflect.Array.get(src, i)));
}
return jsonArray;
} else {
// 其他对象类型,使用默认序列化
return context.serialize(src);
}
}
}
5.2 自定义注解处理
假设我们有一个自定义注解@Encrypt,用于标记需要加密的字段:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Encrypt {
}
我们可以创建一个适配器来处理这个注解:
class EncryptedFieldAdapter implements JsonSerializer<Object>, JsonDeserializer<Object> {
private final Cipher encryptCipher;
private final Cipher decryptCipher;
public EncryptedFieldAdapter() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// 初始化加密和解密的Cipher
SecretKeySpec secretKey = new SecretKeySpec("MySecretKey12345".getBytes(), "AES");
encryptCipher = Cipher.getInstance("AES");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
}
@Override
public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
try {
// 将对象转换为字符串
String plainText = src.toString();
// 加密字符串
byte[] encryptedBytes = encryptCipher.doFinal(plainText.getBytes());
// 将加密后的字节数组转换为Base64编码
String encryptedString = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
return new JsonPrimitive(encryptedString);
} catch (Exception e) {
throw new JsonParseException("Encryption error", e);
}
}
@Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.isJsonNull()) {
return null;
}
try {
// 获取加密的字符串
String encryptedString = json.getAsString();
// 将Base64编码的字符串转换为字节数组
byte[] encryptedBytes = Base64.decode(encryptedString, Base64.DEFAULT);
// 解密字节数组
byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes);
// 转换为原始类型
String plainText = new String(decryptedBytes);
// 根据目标类型进行转换
if (typeOfT == String.class) {
return plainText;
} else if (typeOfT == Integer.class || typeOfT == int.class) {
return Integer.parseInt(plainText);
} else if (typeOfT == Long.class || typeOfT == long.class) {
return Long.parseLong(plainText);
} else {
// 对于其他类型,尝试使用默认反序列化
return context.deserialize(json, typeOfT);
}
} catch (Exception e) {
throw new JsonParseException("Decryption error", e);
}
}
}
六、性能分析与优化
6.1 性能特点
基于JsonTree的适配器相比直接操作流的适配器有以下性能特点:
- 内存开销:需要构建完整的JSON树模型,内存占用较高。
- 处理速度:由于需要两次处理(先构建树,再处理树),处理速度较慢。
- 灵活性:提供了更高的灵活性,可以在处理过程中修改JSON结构。
6.2 性能优化建议
- 避免不必要的树模型:对于结构简单且固定的JSON,优先使用直接操作流的适配器。
- 缓存常用转换逻辑:对于复杂的转换逻辑,考虑缓存中间结果以提高性能。
- 批量处理:在处理大量数据时,考虑批量处理以减少对象创建开销。
- 选择合适的数据结构:在处理大型JSON时,选择高效的数据结构存储中间结果。
七、总结与展望
7.1 JsonTreeBasedAdapter的优势
JsonTreeBasedAdapter作为Gson中基于JSON树模型的适配器,具有以下优势:
- 灵活性:能够处理动态变化的JSON结构,适合复杂场景。
- 易于实现:相比直接操作流的适配器,基于树模型的实现更直观。
- 完整访问:可以完全访问和修改JSON结构,适合需要深度处理的场景。
- 与现有代码集成:便于与使用JsonElement API的现有代码集成。
7.2 未来发展方向
随着JSON处理需求的不断变化,JsonTreeBasedAdapter可能会在以下方向发展:
- 性能优化:通过改进树模型的实现和处理算法,提高性能。
- 异步支持:提供对异步处理的支持,适应现代应用的需求。
- Kotlin协程集成:更好地支持Kotlin协程,简化异步处理逻辑。
- 与其他框架集成:更紧密地集成其他Android和Java框架,提供更统一的API。
- 减少内存占用:优化树模型的内存使用,降低资源消耗。
通过不断优化和扩展,JsonTreeBasedAdapter将继续作为Gson的重要组成部分,为开发者提供灵活、高效的JSON处理解决方案。