GSON反序列化时如何获取ObservableField未初始化的所属对象?
解决方案:通过反射拦截实体类反序列化,传递Owner实例
你的核心问题在于:Gson反序列化时,ObservableField的所属对象(比如Member)会先被创建(通过Unsafe初始化空实例),但ObservableField的构造器必须传入该Owner实例,而单独的ObservableField TypeAdapter无法获取到这个已创建的Owner。
解决思路是不为ObservableField单独编写TypeAdapter,而是为所有包含ObservableField的实体类编写通用TypeAdapterFactory,在实体类反序列化过程中,拿到已创建的实体实例,再为ObservableField字段传入该实例作为Owner。
实现代码
通用TypeAdapterFactory
import com.google.gson.*; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; public class ObservableFieldOwnerTypeAdapterFactory implements TypeAdapterFactory { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { Class<T> clazz = (Class<T>) typeToken.getRawType(); // 检查当前类是否包含ObservableField类型的字段 boolean hasObservableField = Arrays.stream(clazz.getDeclaredFields()) .anyMatch(field -> ObservableField.class.isAssignableFrom(field.getType())); if (!hasObservableField) { return null; // 无ObservableField字段,交给Gson默认适配器处理 } return new TypeAdapter<T>() { @Override public void write(JsonWriter out, T value) throws IOException { // 序列化时直接委托给Gson默认逻辑 gson.getAdapter(typeToken).write(out, value); } @Override public T read(JsonReader in) throws IOException { // 1. 创建未初始化的实体对象(和Gson默认行为一致) T instance = gson.newInstance(typeToken.getType()); // 2. 将JSON解析为JsonObject,方便逐个处理字段 JsonElement jsonElement = gson.fromJson(in, JsonElement.class); JsonObject jsonObject = jsonElement.getAsJsonObject(); // 3. 遍历实体类所有字段 for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); String jsonFieldName = gson.fieldNamingStrategy().translateName(field); JsonElement fieldJson = jsonObject.get(jsonFieldName); if (fieldJson == null) continue; if (ObservableField.class.isAssignableFrom(field.getType())) { // 处理ObservableField类型字段 if (field.getGenericType() instanceof ParameterizedType paramType) { // 获取ObservableField的Value类型参数 Type valueType = paramType.getActualTypeArguments()[1]; Object fieldValue = gson.fromJson(fieldJson, valueType); // 创建ObservableField实例,传入当前实体作为Owner ObservableField<?, ?> observableField = new ObservableField<>(instance, fieldValue); field.set(instance, observableField); } } else { // 处理普通字段,委托给Gson默认反序列化 Object fieldValue = gson.fromJson(fieldJson, field.getGenericType()); field.set(instance, fieldValue); } } return instance; } }; } }
注册Factory到Gson
Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new ObservableFieldOwnerTypeAdapterFactory()) .create(); // 测试反序列化 String json = "{\"id\":\"550e8400-e29b-41d4-a716-446655440000\",\"balance\":100}"; Member member = gson.fromJson(json, Member.class); System.out.println(member.getBalance().getOwner() == member); // 输出true,验证Owner正确关联
关键原理说明
- 拦截实体类反序列化:Factory会自动识别包含
ObservableField的类,为其创建自定义TypeAdapter - 先创建实体实例:利用Gson的
newInstance方法创建未初始化的实体对象(和Gson默认用Unsafe创建的逻辑一致) - 逐个处理字段:解析JSON为JsonObject后,遍历实体字段,遇到
ObservableField时,直接传入已创建的实体实例作为Owner,再赋值给字段 - 兼容普通字段:非
ObservableField字段仍委托给Gson默认反序列化逻辑,保证原有功能不受影响
注意事项
- 确保实体类的字段可以被反射访问(代码中已设置
field.setAccessible(true)) - 如果实体类使用了
@SerializedName注解,gson.fieldNamingStrategy().translateName(field)会自动处理JSON字段名映射 - 若实体类有继承关系,需要额外遍历父类字段(可在代码中添加
Class<?> currentClazz = clazz; while(currentClazz != null) { ... currentClazz = currentClazz.getSuperclass(); }逻辑)
内容的提问来源于stack exchange,提问作者Toshimichi
相关产品推荐
相关产品推荐

