Gson转换复杂对象报错【类型强转错误】

一、问题:

  项目里遇到一个需求,规则文件下载后,导入本地解析。

  采用的方案是:获取复杂对象,使用谷歌Gson转换为字串保存为文件下载,客户端读取文件,解析字串,反解对象

  遇到的问题:传输的对象是一个嵌套的对象,反解的时候会报出类型强转异常

 

二、解决:

  参考网址:【Gson对象转成Java复杂对象出错】 

//规则生成
@RequestMapping(value = {"/getRuleFile"},method = RequestMethod.GET,produces = {"application/json"})
    public void getRuleFile(HttpServletRequest request, HttpServletResponse response,
                            @RequestParam(value = "orgId",required = false)String orgId){

        if(null==orgId || "".equals(orgId)){
            orgId = "";
        }
        List<Rule> ruleList = service.getRuleList(orgId);
        //转换为json
        String ruleStr = gson.toJson(ruleList);
        if("".equals(ruleStr)){
            log.error("转换json字串为空!获取的规则信息有:"+ruleList);
        }else{
            //下载文件
            response.setContentType("text/html;charset=gb2312");
            response.setHeader("Content-Disposition", "attachment; filename=rule.json");
            OutputStream out = null;
            ByteArrayInputStream in = null;
            try {
                out = response.getOutputStream();
                in = new ByteArrayInputStream(ruleStr.getBytes());
                int len = -1;
                byte[] temp = new byte[2048];
                while( (len = in.read(temp)) != -1){
                    out.write(temp,0,len);
                }
            }catch (Exception e){
                log.error("文件下载失败!要下载的文件字串为:"+ruleStr);
                e.printStackTrace();
            }finally {
                try {
                    in.close();
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//文件转换
String filePath = "D://temp/rule.json";
String jsonStr = JsonUtils.readCheckFile(filePath);
List<Rule> ruleList = null;
//需要单独使用反射指定转换的对象类型 List
<Rule> rules = new Gson().fromJson(jsonStr, new TypeToken<List<Rule>>() {}.getType()); int i=0; for(Rule rule : rules) { System.out.println(rule.getCOLUMNRULES().get(i).getTC_RULE_CODE_VALUES()); i++; }

 

三、总结:

  遇到的这个问题,解决的方法很简单,但是网上的很多方法会误导我们。

  找到问题的根源:类型转换时,gson转换的类型和我们期望的类型不匹配,需要反射指定转换的匹配类型

 

转载于:https://www.cnblogs.com/hackxiyu/p/9237373.html

package com.example.kucun2.entity.data; import android.util.Log; import androidx.annotation.NonNull; import com.google.gson.Gson; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import okhttp3.Call; import okhttp3.Callback; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * 支持数据变更自动同步的泛型集合类 * @param <T> 继承自 SynchronizableEntity 的实体类型 */ 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 final Class<T> entityClass; // 类型标记 // 添加批量操作模式标志 private boolean batchMode = false; // 属性变更监听器 private final List<PropertyChangeListener<T>> listeners = new ArrayList<>(); public SynchronizedList(Class<T> entityClass) { Type superClass = getClass().getGenericSuperclass(); ParameterizedType type = (ParameterizedType) superClass; Type[] typeArgs = type.getActualTypeArguments(); this.entityClass = (Class<T>) typeArgs[0]; } // 安全的类型转换方法 private T safeCast(Object o) { if (o != null && entityClass.isInstance(o)) { return entityClass.cast(o); } return null; } public interface PropertyChangeListener<T> { void onPropertyChange(T entity, String propertyName, Object oldValue, Object newValue); } public void addPropertyChangeListener(PropertyChangeListener<T> listener) { listeners.add(listener); } public void removePropertyChangeListener(PropertyChangeListener<T> listener) { listeners.remove(listener); } // 添加方法来获取原始对象 @SuppressWarnings("unchecked") public T getOriginal(T proxy) { if (proxy instanceof java.lang.reflect.Proxy) {//报错无法转换!!! java.lang.reflect.InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(proxy); if (handler instanceof EntityProxyHandler) {//报错无法安全转换!!! return ((EntityProxyHandler<T>) handler).getOriginal(); } } return proxy; } /** * 同步实体到后端 * @param entity 要同步的实体 */ private void syncEntity(T entity) { if (batchMode) return; String operation="add"; T originalEntity = getOriginal(entity); String endpoint = originalEntity.getEndpoint(operation); String json = gson.toJson(originalEntity); RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(endpoint) .method(getHttpMethod(operation), body) .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.message()); } response.close(); } }); } // 添加用于批量操作的方法 public void beginBatch() { this.batchMode = true; } public void endBatch() { this.batchMode = false; // 批量结束后触发一次全量同步 syncAllEntities(); } private void syncAllEntities() { for (T entity : list) { syncEntity(entity); } } private String getHttpMethod(String operation) { switch (operation) { case "add": return "POST"; case "update": return "PUT"; case "delete": return "DELETE"; default: return "POST"; } } /** * 创建代理对象,用于监听属性变更 */ private T createProxy(T original) { if (!entityClass.isInstance(original)) { throw new IllegalArgumentException("Invalid entity type"); } // 这里使用动态代理模式监听setter方法调用 return (T) java.lang.reflect.Proxy.newProxyInstance( original.getClass().getClassLoader(), original.getClass().getInterfaces(), (proxy, method, args) -> { // 只拦截setter方法 if (method.getName().startsWith("set") && args.length == 1) { String propertyName = method.getName().substring(3); propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); // 获取旧值 Object oldValue = original.getClass() .getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)) .invoke(original); // 调用原始方法 Object result = method.invoke(original, args); // 触发监听器 for (PropertyChangeListener<T> listener : listeners) { listener.onPropertyChange(original, propertyName, oldValue, args[0]); } // 自动同步到后端 syncEntity(original); return result; } return method.invoke(original, args); } ); } // 以下是List接口的实现 @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 add(T t) { T proxy = createProxy(t); boolean result = list.add(proxy); if (!batchMode) { syncEntity(proxy); } return result; // 添加时创建代理 } @Override public boolean remove(Object o) { T entity = safeCast(o); if (entity != null) { syncEntity((T) entity); // 删除前同步 } return list.remove(o); } @Override public boolean containsAll(@NonNull Collection<?> c) { return list.containsAll(c); } @Override public boolean addAll(@NonNull Collection<? extends T> c) { boolean modified = false; for (T t : c) { modified |= add(t); } return modified; } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { for (T t : c) { add(index++, t); } return true; } @Override public boolean removeAll(@NonNull Collection<?> c) { for (Object o : c) { T entity = safeCast(o); if (entity != null) { syncEntity(entity); } } return list.removeAll(c); } @Override public boolean retainAll(@NonNull Collection<?> c) { List<T> toRemove = new ArrayList<>(); for (T t : list) { if (!c.contains(t)) { toRemove.add(t); } } // 使用安全转换 for (T entity : toRemove) { syncEntity(entity); } return list.retainAll(c); } @Override public void clear() { for (T t : list) { syncEntity(t); // 清空前同步 } list.clear(); } @Override public T get(int index) { return list.get(index); } @Override public T set(int index, T element) { T old = list.set(index, createProxy(element)); if (old != null) { syncEntity(old); // 替换旧元素前同步 } return old; } @Override public void add(int index, T element) { list.add(index, createProxy(element)); } @Override public T remove(int index) { T removed = list.remove(index); if (removed != null) { syncEntity(removed); // 删除前同步 } return removed; } @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 list.subList(fromIndex, toIndex); } // 修改代理处理器以支持获取原始对象 private class EntityProxyHandler<T> implements java.lang.reflect.InvocationHandler { private final T original; public EntityProxyHandler(T original) { this.original = original; } public T getOriginal() { return original; } @Override public Object invoke(Object proxy, Method method, Object[] args) { // 处理setter方法 if (method.getName().startsWith("set") && args.length == 1) { String propertyName = method.getName().substring(3); propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1); // 获取旧值 Object oldValue = getPropertyValue(propertyName); // 执行实际setter Object result = method.invoke(original, args); // 触发监听 firePropertyChange(original, propertyName, oldValue, args[0]);//没有实现方法 // 非批量模式下自动同步 if (!batchMode) { syncEntity(original, "update"); } return result; } // 处理getOriginal方法 if ("getOriginal".equals(method.getName())) { return original; } return method.invoke(original, args); } private Object getPropertyValue(String propertyName) { String getterName = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); try { Method getter = original.getClass().getMethod(getterName); return getter.invoke(original); } catch (Exception e) { return null; } } } }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.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);//参数不对报错 // 结束批量模式(会触发一次全量同步) 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() { // 创建ID到对象的映射 Map<Integer, Bancai> bancaiMap = createIdMap(bancais); Map<Integer, Caizhi> caizhiMap = createIdMap(caizhis); Map<Integer, Mupi> mupiMap = createIdMap(mupis); Map<Integer, Chanpin> chanpinMap = createIdMap(chanpins); Map<Integer, Zujian> zujianMap = createIdMap(zujians); Map<Integer, Dingdan> dingdanMap = createIdMap(dingdans); Map<Integer, Kucun> kucunMap = createIdMap(kucuns); // 解析Bancai引用 for (Bancai banca : bancais) { Bancai bancai = bancais.getOriginal(banca); if (bancai.getCaizhi() != null) { bancai.setCaizhi(caizhiMap.get(bancai.getCaizhi().getId())); } if (bancai.getMupi1() != null) { bancai.setMupi1(mupiMap.get(bancai.getMupi1().getId())); } if (bancai.getMupi2() != null) { bancai.setMupi2(mupiMap.get(bancai.getMupi2().getId())); } } // 解析Kucun引用 for (Kucun kucu : kucuns) { Kucun kucun = kucuns.getOriginal(kucu); if (kucun.getBancai() != null) { kucun.setBancai(bancaiMap.get(kucun.getBancai().getId())); } } // 解析订单相关的嵌套对象 for (Dingdan_Chanpin dca : dingdanChanpins) { Dingdan_Chanpin dc = dingdanChanpins.getOriginal(dca); if (dc.getDingdan() != null) { dc.setDingdan(dingdanMap.get(dc.getDingdan().getId())); } if (dc.getChanpin() != null) { dc.setChanpin(chanpinMap.get(dc.getChanpin().getId())); } } // 解析产品相关的嵌套对象 for (Chanpin_Zujian czz : chanpinZujians) { Chanpin_Zujian cz = chanpinZujians.getOriginal(czz); if (cz.getChanpin() != null) { cz.setChanpin(chanpinMap.get(cz.getChanpin().getId())); } if (cz.getZujian() != null) { cz.setZujian(zujianMap.get(cz.getZujian().getId())); } if (cz.getBancai() != null) { cz.setBancai(bancaiMap.get(cz.getBancai().getId())); } } // 解析库存关联 for (Kucun ks : kucuns) { Kucun k = kucuns.getOriginal(ks); if (k.getBancai() != null) { k.setBancai(bancaiMap.get(k.getBancai().getId())); } } } // 创建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 addToGlobalMap(Map<Integer, EntityClassGrassrootsid> map, SynchronizedList<? extends EntityClassGrassrootsid> list) { for (EntityClassGrassrootsid entity : list) { EntityClassGrassrootsid original = list.getOriginal(entity)/*报错*/; map.put(original.getId(), original); } } private static void resolveEntityReferences(SynchronizedList<?> list, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Object item : list) { resolveFields(list.getOriginal(item)/*报错*/, globalMap); } } 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; } }
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值