Gson - Arrays 和 Lists 对象映射

本文详细介绍了如何使用 Gson 库进行 Arrays 和 Lists 对象的序列化与反序列化。讨论了 Array 和 List 在 Java 中的差异,以及在 JSON 中的表示形式。通过示例展示了如何将对象映射到 JSON 数组和列表,以及如何将 JSON 数据转换回 Java 对象,包括嵌套 List 的处理。还涵盖了在实际开发中选择使用 Array 或 List 的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接:Gson — Mapping of Arrays and Lists of Objects
原文出自:Norman Peitek
译者:無名無

欢迎到我们的 Gson 系列的另一篇文章,在回顾了 Gson 的基础用法之后,例如:模型注解和嵌套对象的映射,我们来讨论本文重点功能:数组和列表对象的映射,我们几乎都会使用到这种数据类型,幸运的是,Gson 可以帮我们轻松搞定。

Array 和 List 差异

在我们介绍序列化之前,我们先来看下 Java 中的两种数据结构:Array 和 List。在 Java 中两者实现方式不同,使用哪一种数据类型取决于你的实际需求,但是在序列化这个问题上, Gson 并不关心这两种数据结构的具体实现。

在 JSON 数据格式中,不存在数组等结构,只是 Java 的具体实现使得这两种数据类型有很大不同。但是在上层它们表示出相同的结构,接下来,我们将重新理解这两种数据类型,在看过几个例子之后你就懂了。

Array 和 List 序列化

还记得上一篇关于 restaurant model 的嵌套对象吗?接下来,我们为restaurant 添加一个 menu 属性,包含两个字段,restaurant 中的菜单可以理解成一个 restaurant 列表。如下:

提示:我们这里只是简单的举个菜单的例子,这个数据结构不是一个完整的数据,所以它是不能被真实使用的。

首先要创建一个 Java model 类:

public class RestaurantWithMenu { 
    String name;

    List<RestaurantMenuItem> menu;
    //RestaurantMenuItem[] menu; // alternative, either one is fine
}

public class RestaurantMenuItem { 
    String description;
    float price;
}

通过嵌套对象的方式即可,在 Java Model 中包含要映射变量的引用就可以了,要注意名字和JSON中字段名相同。

JSON 格式如下:

{
    "name": "Future Studio Steak House",
    "menu": [
    ...
    ]
}

与嵌套对象类似,我们没有 menu 的直接值,相反,JSON 中通过 “[]” 来包含一个对象,如上所述,在 JSON 数据中,数组和 List 结构是没有区别的。

menu 中包含一些对象,在我们那的 model 中,menu 只是其中的一个变量,我们先来手动生成一个完整的 JSON 数据。

通过下面这种方式,我们来模拟一个完整的 restaurant 数据:

List<RestaurantMenuItem> menu = new ArrayList<>();
menu.add(new RestaurantMenuItem("Spaghetti", 7.99f));
menu.add(new RestaurantMenuItem("Steak", 12.99f));
menu.add(new RestaurantMenuItem("Salad", 5.99f));

RestaurantWithMenu restaurant = new RestaurantWithMenu("Future Studio Steak House", menu);

Gson gson = new Gson();
String restaurantJson = gson.toJson(restaurant);

生成JSON如下:

{
    "menu": [
    {
        "description": "Spaghetti",
        "price": 7.99
    },
    {
        "description": "Steak",
        "price": 12.99
    },
    {
        "description": "Salad",
        "price": 5.99
        }
    ],
    "name": "Future Studio Steak House"
}

如我们预料,我们得到了想要的数据,按照字母顺序,menu 排在了name 的前面,根据 “[]” 标志 List 开始,根据 “{}” 标志对象开始。

但是我们并不是总是将 List 嵌套在对象中,我们可能会直接得到一个 List,Gson 也是支持直接序列化一个 List。

List<RestaurantMenuItem> menu = new ArrayList<>();
menu.add(new RestaurantMenuItem("Spaghetti", 7.99f));
menu.add(new RestaurantMenuItem("Steak", 12.99f));
menu.add(new RestaurantMenuItem("Salad", 5.99f));

Gson gson = new Gson();
String menuJson = gson.toJson(menu);

输出:

[
    {
        "description": "Spaghetti",
        "price": 7.99
    },
    {
        "description": "Steak",
        "price": 12.99
    },
    {
        "description": "Salad",
        "price": 5.99
    }
]

来看下数据中的不同,JSON 中的 “[” 表示一个对象列表开始,”{“表示一个对象开始了,我们应该记住 JSON 数据中格式差别。

数组和 List 反序列化

在第二部分我们将学习反序列化,我们将使用 Gson 来解析列表数据,在之前的例子中,我们列举了两种情况,一是列表作为跟节点,二是列表最为一个嵌套对象。

List作为跟节点

来看一个列表最为根节点的例子:

[
    {
        "name": "Christian",
        "flowerCount": 1
    },
     {
        "name": "Marcus",
        "flowerCount": 3
    },
     {
        "name": "Norman",
         "flowerCount": 2
   }

]

根据之前介绍的,”[]”标示一个GSON 解析列表的开始和结束,我们还需要一个具体的 Java model类:

public class Founder {
    String name;
    int flowerCount;
}

接下来,我们将数据解析成我们想要的数据类型。

数组:

首先看解析成数组,通过 Gson 的 gson.fromJson 方法,我们很简单的将 GSON 解析成数组,注意这里传递的参数是 Founder[].class 而不是Founder.class ,如下:

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();
Founder[] founderArray = gson.fromJson(founderJson, Founder[].class);

Debug 如下:

founderArray

Lists

实际开发中,我们更多的是转成一个 ArrayList,但是,我们不能像解析数组那样传入 List,为了让Gson知道我们要解析的数据类型,我们必须传递给它一个Type,内部根据 TypeToken 来区分要解析的类型。例如:

Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();

完成解析如下:

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();

Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();

List<Founder> founderList = gson.fromJson(founderJson, founderListType);

Debug如下:

founderList

以上两种方式,根据自己实际需求选择。接下来来看看反序列化操作。

### 列表作为对象的一部分

我们现在有一个这样的数据:

   {
    "name": "Future Studio Dev Team",
    "website": "https://futurestud.io",
    "founders": [{
        "name": "Christian",
        "flowerCount": 1
    }, {
        "name": "Marcus",
        "flowerCount": 3
    }, {
        "name": "Norman",
        "flowerCount": 2
    }]
   }

老样子我们需要创建一个用来对应的 Java Model 类:

public class GeneralInfo {
    String name;
    String website;
    List<Founder> founders;
}

列表存在 Model 类中的一个好处就是,我们在使用Gson解析时不再需要传递 TypeToken,直接穿入类即可。

String generalInfoJson = "{'name': 'Future Studio Dev Team', 'website': 'https://futurestud.io', 'founders': [{'name': 'Christian', 'flowerCount': 1 }, {'name': 'Marcus','flowerCount': 3 }, {'name': 'Norman','flowerCount': 2 }]}";

Gson gson = new Gson();

GeneralInfo generalInfoObject = gson.fromJson(generalInfoJson, GeneralInfo.class);

Debug如下:

GeneralInfo

除了解析成一个 List,也可以解析为数组格式。

List 中嵌套 List

Gson 也可以解析 List 中嵌套 List 数据结构,看下面这个例子,例如:

public class GeneralInfo {
    String name;
    String website;
    List<FounderWithPets> founders;
}

public class FounderWithPets {
    String name;
    int flowerCount;
    List<Pet> pets;
}

public class Pet {
    String name;
    List<Toy> toys;
}

JSON 中包含了三个 List,这里就不操作了,相信 Gson 也是可以解析的。只要我们将需要解析的类型传递正确就可以。

目标

本文你将了解如何使用Gson 来序列化和反序列化 ArrayList 和 数组,知道了如何根据 JSON 格式中的不同来判断是对象还是一个对象集合。

你可以通过评论或twitter @futurestud_io 反馈你的问题。

练习代码已上传 Github https://github.com/whiskeyfei/Gson-Review 可自行查看。

Gson 系列文章翻译回顾

1、Gson - Java-JSON 序列化和反序列化入门
2、Gson - 映射嵌套对象
3、Gson - Arrays 和 Lists 映射对象
4、Gson - Map 结构映射
5、Gson - Set 集合映射
6、Gson - 空值映射
7、Gson Model Annotations - 如何使用 @SerializedName 更改字段的命名
8、Gson Model Annotations - @SerializedName 匹配多个反序列化名称
9、Gson Builder - 基础和命名规则
10、Gson Builder - 序列化空值
11、Gson Builder - 忽略策略
12、Gson Builder - Gson Lenient 属性
13、Gson Builder - 特殊类型 Floats & Doubles
17、Gson Builder - 如何使用 @Expose 忽略字段
19、Gson Advanced - 映射枚举类型
20、Gson Advanced - 映射循环引用
21、Gson Advanced - 泛型
22、Gson Advanced - 简单自定义序列化 (Part 1)
24、Gson Advanced - 自定义反序列化基础
25、Gson Advanced - 自定义对象实例创建
26、Gson Advanced - 通过 @JsonAdapter 自定义(反)序列化过程
32、Practical Gson - 如何解析多态对象

package com.example.kucun2.entity.data; import android.util.Log; import androidx.annotation.NonNull; import com.example.kucun2.function.MyAppFnction; import com.google.gson.Gson; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.*; import okhttp3.*; /** * 支持数据变更自动同步的泛型集合类 * 移除了代理机制,改用基类的事件监听 */ public class SynchronizedList<T extends SynchronizableEntity> implements List<T> { private final List<T> list = new ArrayList<>(); private final OkHttpClient client = new OkHttpClient(); private static final Gson gson = new Gson(); private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); // 批量操作模式标志 private boolean batchMode = false; // 实体变更监听器 private final EntityChangeListener<T> listener = entity -> { if (!batchMode) syncEntity(entity); }; // 直接接受Class参数的构造函数 public SynchronizedList(Class<T> T) {} // 添加监听器的方法 private void registerListener(T entity) { if (entity != null) { entity.addPropertyChangeListener(listener); } } private void unregisterListener(T entity) { if (entity != null) { entity.removePropertyChangeListener(listener); } } private String getUrl() { return MyAppFnction.getStringResource("string", "url"); } /** * 同步实体到后端 */ private static void syncEntity(SynchronizableEntity entity) { String operation = "update"; // 默认为更新操作 String endpoint = entity.getEndpoint(operation); String json = gson.toJson(entity); RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(getUrl() + endpoint) .put(body) // 统一使用PUT方法 .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("SynchronizedList", "同步失败: " + entity.getClass().getSimpleName(), e); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if (!response.isSuccessful()) { Log.e("SynchronizedList", "同步失败: " + response.code()); } response.close(); } }); } // 批量操作方法 public void beginBatch() { this.batchMode = true; } public void endBatch() { this.batchMode = false; syncAllEntities(); } private void syncAllEntities() { for (T entity : list) { syncEntity(entity); } } // List接口实现(添加时注册监听器,移除时取消监听) @Override public boolean add(T t) { registerListener(t); boolean result = list.add(t); if (!batchMode) syncEntity(t); return result; } @Override public void add(int index, T element) { registerListener(element); list.add(index, element); if (!batchMode) syncEntity(element); } @Override public boolean remove(Object o) { if (o instanceof SynchronizableEntity) { T entity = (T) o; unregisterListener(entity); if (!batchMode) syncEntity(entity); } return list.remove(o); } @Override public T remove(int index) { T entity = list.get(index); if (entity != null) { unregisterListener(entity); if (!batchMode) syncEntity(entity); } return list.remove(index); } @Override public boolean addAll(@NonNull Collection<? extends T> c) { for (T t : c) registerListener(t); return list.addAll(c); } @Override public boolean removeAll(@NonNull Collection<?> c) { for (Object o : c) { if (o instanceof SynchronizableEntity) { unregisterListener((T) o); } } return list.removeAll(c); } @Override public boolean retainAll(@NonNull Collection<?> c) { return false; } @Override public void clear() { for (T t : list) { unregisterListener(t); if (!batchMode) syncEntity(t); } list.clear(); } @Override public T get(int index) { return list.get(index); } @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @NonNull @Override public Iterator<T> iterator() { return list.iterator(); } @NonNull @Override public Object[] toArray() { return list.toArray(); } @NonNull @Override public <T1> T1[] toArray(@NonNull T1[] a) { return list.toArray(a); } @Override public boolean containsAll(@NonNull Collection<?> c) { return list.containsAll(c); } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { for (T element : c) { registerListener(element); } boolean result = list.addAll(index, c); if (!batchMode) { for (T element : c) { syncEntity(element); } } return result; } @Override public T set(int index, T element) { T oldElement = list.set(index, element); // 取消旧元素的监听 if (oldElement != null) { unregisterListener(oldElement); if (!batchMode) syncEntity(oldElement); } // 注册新元素的监听 registerListener(element); if (!batchMode) { syncEntity(element); } return oldElement; } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @NonNull @Override public ListIterator<T> listIterator() { return list.listIterator(); } @NonNull @Override public ListIterator<T> listIterator(int index) { return list.listIterator(index); } @NonNull @Override public List<T> subList(int fromIndex, int toIndex) { // 创建子列表的同步包装器 return new SynchronizedListWrapper(list.subList(fromIndex, toIndex)); } // 其他List接口方法保持原样... // [此处省略未修改的List接口方法实现] /** * 实体变更监听接口 */ public interface EntityChangeListener<T> extends PropertyChangeListener { default void onPropertyChange(T entity, String propertyName, Object oldValue, Object newValue) { syncEntity((SynchronizableEntity) entity); } } // ==================== 内部辅助类 ==================== private class SynchronizedListWrapper implements List<T> { private final List<T> wrapped; public SynchronizedListWrapper(List<T> list) { this.wrapped = list; } @Override public boolean add(T element) { registerListener(element); boolean result = wrapped.add(element); if (!batchMode) syncEntity(element); return result; } @Override public void add(int index, T element) { registerListener(element); wrapped.add(index, element); if (!batchMode) syncEntity(element); } @Override public T set(int index, T element) { T oldElement = wrapped.get(index); if (oldElement != null) { unregisterListener(oldElement); if (!batchMode) syncEntity(oldElement); } registerListener(element); T result = wrapped.set(index, element); if (!batchMode) syncEntity(element); return result; } @Override public T remove(int index) { T element = wrapped.get(index); if (element != null) { unregisterListener(element); if (!batchMode) syncEntity(element); } return wrapped.remove(index); } @Override public boolean remove(Object o) { if (o instanceof SynchronizableEntity) { T entity = (T) o; if (wrapped.contains(entity)) { unregisterListener(entity); if (!batchMode) syncEntity(entity); } } return wrapped.remove(o); } @Override public boolean addAll(@NonNull Collection<? extends T> c) { for (T element : c) { registerListener(element); } boolean result = wrapped.addAll(c); if (!batchMode) { for (T element : c) { syncEntity(element); } } return result; } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { for (T element : c) { registerListener(element); } boolean result = wrapped.addAll(index, c); if (!batchMode) { for (T element : c) { syncEntity(element); } } return result; } @Override public boolean removeAll(@NonNull Collection<?> c) { // 先取消所有要移除元素的监听器 for (Object o : c) { if (o instanceof SynchronizableEntity) { T entity = (T) o; if (wrapped.contains(entity)) { unregisterListener(entity); if (!batchMode) syncEntity(entity); } } } return wrapped.removeAll(c); } @Override public boolean retainAll(@NonNull Collection<?> c) { // 找出要移除的元素 List<T> toRemove = new ArrayList<>(); for (T element : wrapped) { if (!c.contains(element)) { toRemove.add(element); } } // 取消这些元素的监听器 for (T element : toRemove) { unregisterListener(element); if (!batchMode) syncEntity(element); } return wrapped.retainAll(c); } @Override public void clear() { // 取消所有元素的监听器 for (T element : wrapped) { unregisterListener(element); if (!batchMode) syncEntity(element); } wrapped.clear(); } // ---------------- 以下是非修改方法,直接委托给包装列表 ---------------- @Override public int size() { return wrapped.size(); } @Override public boolean isEmpty() { return wrapped.isEmpty(); } @Override public boolean contains(Object o) { return wrapped.contains(o); } @NonNull @Override public Iterator<T> iterator() { return wrapped.iterator(); } @NonNull @Override public Object[] toArray() { return wrapped.toArray(); } @NonNull @Override public <T1> T1[] toArray(@NonNull T1[] a) { return wrapped.toArray(a); } @Override public boolean containsAll(@NonNull Collection<?> c) { return wrapped.containsAll(c); } @Override public T get(int index) { return wrapped.get(index); } @Override public int indexOf(Object o) { return wrapped.indexOf(o); } @Override public int lastIndexOf(Object o) { return wrapped.lastIndexOf(o); } @NonNull @Override public ListIterator<T> listIterator() { return wrapped.listIterator(); } @NonNull @Override public ListIterator<T> listIterator(int index) { return wrapped.listIterator(index); } @NonNull @Override public List<T> subList(int fromIndex, int toIndex) { return new SynchronizedListWrapper(wrapped.subList(fromIndex, toIndex)); } } }package com.example.kucun2.entity.data; import android.content.Context; import android.util.Log; import com.example.kucun2.entity.*; import com.example.kucun2.function.MyAppFnction; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.*; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class Data { // 数据集合声明(保持原有属性名不变) public static SynchronizedList<Bancai> bancais = new SynchronizedList<>(Bancai.class); public static SynchronizedList<Caizhi> caizhis = new SynchronizedList<>(Caizhi.class); public static SynchronizedList<Mupi> mupis = new SynchronizedList<>(Mupi.class); public static SynchronizedList<Chanpin> chanpins = new SynchronizedList<>(Chanpin.class); public static SynchronizedList<Chanpin_Zujian> chanpinZujians = new SynchronizedList<>(Chanpin_Zujian.class); public static SynchronizedList<Dingdan> dingdans = new SynchronizedList<>(Dingdan.class); public static SynchronizedList<Dingdan_Chanpin> dingdanChanpins = new SynchronizedList<>(Dingdan_Chanpin.class); public static SynchronizedList<Dingdan_Bancai> dingdanBancais = new SynchronizedList<>(Dingdan_Bancai.class); public static SynchronizedList<Kucun> kucuns = new SynchronizedList<>(Kucun.class); public static SynchronizedList<Zujian> zujians = new SynchronizedList<>(Zujian.class); public static SynchronizedList<User> users = new SynchronizedList<>(User.class); public static SynchronizedList<Jinhuo> jinhuoList = new SynchronizedList<>(Jinhuo.class); private static final Gson gson = new Gson(); private static final OkHttpClient client = new OkHttpClient(); private static final String TAG = "DataLoader"; // 加载所有数据的方法 public static void loadAllData(Context context, LoadDataCallback callback) { // 开始批量模式 for (SynchronizedList<?> list : getAllSyncLists()) { list.beginBatch(); } String url = MyAppFnction.getStringResource("String", "url") + MyAppFnction.getStringResource("String", "url_all"); Request request = new Request.Builder() .url(url) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "Failed to load data", e); if (callback != null) callback.onFailure(); } @Override public void onResponse(Call call, Response response) throws IOException { parseAndAssignData(response.body().string(), context,callback); // 结束批量模式(会触发一次全量同步) for (SynchronizedList<?> list : getAllSyncLists()) { list.endBatch(); } if (callback != null) callback.onSuccess(); } }); } // 获取所有同步列表的方法 private static List<SynchronizedList<?>> getAllSyncLists() { return Arrays.asList(bancais, caizhis, mupis, chanpins, chanpinZujians, dingdans, dingdanChanpins, dingdanBancais, kucuns, zujians, users, jinhuoList); } // 解析并赋值数据 private static void parseAndAssignData(String jsonData, Context context, LoadDataCallback callback) { // 创建包含所有数据类型的TypeToken Type informationType = new TypeToken<Information<AllDataResponse>>(){}.getType(); Information<AllDataResponse> information = gson.fromJson(jsonData, informationType); if (information == null || information.getData() == null || information.getStatus() != 200) { Log.e(TAG, "Invalid response data"); if (callback != null) callback.onFailure(); return; } AllDataResponse allData = information.getData(); // 赋值到对应的列表(使用安全方法保持已有引用) updateList(bancais, allData.bancais); updateList(caizhis, allData.caizhis); updateList(mupis, allData.mupis); updateList(chanpins, allData.chanpins); updateList(chanpinZujians, allData.chanpin_zujians); updateList(dingdans, allData.dingdans); updateList(dingdanChanpins, allData.dingdan_chanpins); updateList(dingdanBancais, allData.dingdan_bancais); updateList(kucuns, allData.kucuns); updateList(zujians, allData.zujians); updateList(users, allData.users); updateList(jinhuoList, allData.jinhuos); resolveReferences(); if (callback != null) callback.onSuccess(); } // 更新列表内容但保持对象引用不变 private static <T> void updateList(List<T> existingList, List<T> newList) { if (newList == null) return; existingList.clear(); for (T item : newList) { existingList.add(item); // 会被包装成代理对象 } } // 解析对象间的引用关系(使用ID关联) // 改进的引用解析方法 private static void resolveReferences() { // 创建全局对象映射 Map<Integer, EntityClassGrassrootsid> globalMap = new HashMap<>(); // 填充全局映射表 addToGlobalMap(globalMap, bancais); addToGlobalMap(globalMap, caizhis); addToGlobalMap(globalMap, mupis); addToGlobalMap(globalMap, chanpins); addToGlobalMap(globalMap, zujians); addToGlobalMap(globalMap, dingdans); addToGlobalMap(globalMap, kucuns); addToGlobalMap(globalMap, users); // 解析所有实体的引用 resolveListReferences(bancais, globalMap); resolveListReferences(kucuns, globalMap); resolveListReferences(dingdanChanpins, globalMap); resolveListReferences(chanpinZujians, globalMap); resolveListReferences(dingdanBancais, globalMap); resolveListReferences(jinhuoList, globalMap); } // 添加对象到全局映射表 private static void addToGlobalMap(Map<Integer, EntityClassGrassrootsid> map, SynchronizedList<?> list) { for (Object item : list) { Object original = getOriginalFromList(list, item); if (original instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid entity = (EntityClassGrassrootsid) original; map.put(entity.getId(), entity); } } } // 解析列表中所有实体的引用 private static void resolveListReferences(SynchronizedList<?> list, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Object item : list) { Object original = getOriginalFromList(list, item); resolveEntityReferences(original, globalMap); } } // 安全获取原始对象(无需类型转换) @SuppressWarnings("unchecked") private static <T> T getOriginalFromList(SynchronizedList<?> list, Object item) { try { // 使用反射调用getOriginal方法 Method getOriginal = list.getClass().getMethod("getOriginal", Object.class); return (T) getOriginal.invoke(list, item); } catch (Exception e) { Log.e("Data", "Failed to get original object", e); return (T) item; } } //解析集合中的引用 private static void resolveCollectionReferences(Collection<?> collection, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Object item : collection) { if (item instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid ref = (EntityClassGrassrootsid) item; EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && ref.getClass().isInstance(resolved)) { // 注意:直接替换集合元素需要特殊处理 // 实际项目应考虑使用CopyOnWrite集合或创建新集合 if (collection instanceof List) { int index = ((List<?>) collection).indexOf(ref); if (index != -1) { try { ((List<Object>) collection).set(index, resolved); } catch (Exception e) { Log.e("Data", "Failed to update collection", e); } } } } } } } // 解析单个实体的引用 private static void resolveEntityReferences(Object entity, Map<Integer, EntityClassGrassrootsid> globalMap) { if (entity == null) return; // 如果是代理对象则获取原始对象 Object target = entity; if (entity instanceof SynchronizedList.IProxyHandler) { target = ((SynchronizedList.IProxyHandler) entity).getOriginal(); } Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { try { field.setAccessible(true); // 处理基本类型字段 if (EntityClassGrassrootsid.class.isAssignableFrom(field.getType())) { EntityClassGrassrootsid ref = (EntityClassGrassrootsid) field.get(entity); if (ref != null && ref.getId() != null) { EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && field.getType().isInstance(resolved)) { field.set(entity, resolved); } } } // 处理集合类型字段 else if (Collection.class.isAssignableFrom(field.getType())) { Collection<?> collection = (Collection<?>) field.get(entity); if (collection != null) { resolveCollectionReferences(collection, globalMap); } } } catch (Exception e) { Log.e("Data", "Error resolving field: " + field.getName(), e); } } } // 创建ID到对象映射 private static <T extends EntityClassGrassrootsid> Map<Integer, T> createIdMap(List<T> list) { Map<Integer, T> map = new HashMap<>(); for (T item : list) { map.put(item.getId(), item); } return map; } // 回调接口 public interface LoadDataCallback { void onSuccess(); void onFailure(); } private static void resolveFields(Object entity, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Field field : entity.getClass().getDeclaredFields()) { if (EntityClassGrassrootsid.class.isAssignableFrom(field.getType())) { try { field.setAccessible(true); EntityClassGrassrootsid ref = (EntityClassGrassrootsid) field.get(entity); if (ref != null) { EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && field.getType().isAssignableFrom(resolved.getClass())) { field.set(entity, resolved); } } } catch (Exception e) { Log.e("Data", "Error resolving reference", e); } } } } // 内部类用于解析JSON响应 public static class AllDataResponse { public List<Bancai> bancais; public List<Caizhi> caizhis; public List<Mupi> mupis; public List<Chanpin> chanpins; public List<Chanpin_Zujian> chanpin_zujians; public List<Dingdan> dingdans; public List<Dingdan_Chanpin> dingdan_chanpins; public List<Dingdan_Bancai> dingdan_bancais; public List<Kucun> kucuns; public List<Zujian> zujians; public List<User> users; public List<Jinhuo> jinhuos; } }package com.example.kucun2.entity.data; import android.util.Log; import com.example.kucun2.function.MyAppFnction; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.HashMap; import java.util.Map; public abstract class SynchronizableEntity implements EntityClassGrassrootsid { // 使用标准属性变更支持类 private transient PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); // 属性缓存(可选,用于优化) private final Map<String, Object> propertyCache = new HashMap<>(); // 添加属性变更监听器 public void addPropertyChangeListener(PropertyChangeListener listener) { if (changeSupport == null) { changeSupport = new PropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(listener); } // 移除属性变更监听器 public void removePropertyChangeListener(PropertyChangeListener listener) { if (changeSupport != null) { changeSupport.removePropertyChangeListener(listener); } } // 触发属性变更通知(子类在setter中调用) protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null && changeSupport.hasListeners(propertyName)) { // 更新属性缓存(可选) propertyCache.put(propertyName, newValue); // 触发变更事件 changeSupport.firePropertyChange(propertyName, oldValue, newValue); } } // 获取属性当前值(可选,用于setter中获取旧值) protected <T> T getCachedProperty(String propertyName) { return (T) propertyCache.get(propertyName); } // 初始化属性缓存(可选,在构造函数中调用) protected void initPropertyCache() { // 初始化所有字段到缓存 for (java.lang.reflect.Field field : getClass().getDeclaredFields()) { try { field.setAccessible(true); propertyCache.put(field.getName(), field.get(this)); } catch (Exception e) { // 忽略初始化异常 } } } /** * 添加url * @param type 操作增删改查 * @return 返回相对url */ public String getEndpoint(String type){ //从String.xml获取url Log.d("getEndpoint", "getEndpoint: "+"url_"+type+"_"+this.getClass().getSimpleName().toLowerCase()); return MyAppFnction.getStringResource("string","url_"+type+"_"+this.getClass().getSimpleName().toLowerCase()); } public void sync(){ } }
最新发布
06-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值