zhou-you / RxEasyHttp

本库是一款基于RxJava2+Retrofit2实现简单易用的网络请求框架,结合android平台特性的网络封装库,采用api链式调用一点到底,集成cookie管理,多种缓存模式,极简https配置,上传下载进度显示,请求错误自动重试,请求携带token、时间戳、签名sign动态配置,自动登录成功后请求重发功能,3种层次的参数设置默认全局局部,默认标准ApiResult同时可以支持自定义的数据结构,已经能满足现在的大部分网络请求。
Apache License 2.0
3.13k stars 616 forks source link

关于有些公司的后台是PHP,json返回的数据格式不统一问题的解决办法 #151

Closed amosxb closed 5 years ago

amosxb commented 5 years ago

比如会出现有数据是返回data对象,没有数据时返回data数组或者data=null

建议引用gson-plugin插件,该插件可以完美的解决解析json时因为数据格式不统一导致解析失败,从而不能获取到正确返回的数据。

github地址:https://github.com/LianjiaTech/gson-plugin

问题是Rxjava2 onNext不能返回null 这个库如果没有data 可以给data赋值之类的吗

githubghb commented 5 years ago

上传表单的时候,如果有附件和其他字段一起上传,后台就获取不到token,这个怎么办,好急!

amber-yi commented 5 years ago

新项目是想使用这个库,然后确实遇见了数据解析方面的错,主要是以前公司后台返回的数据结构都是统一的,但是这次项目后端是外包的,后台返回格式是正确的时候是只有我们需要的数据 [ { "categoryId": 108902, "children": [ { "categoryId": 108903, "children": [], "code": "002", "createTime": 1558322493000, "createdBy": null, "deleted": false, "description": "描述", "displayOrder": 1, "enabled": true, "icon": "", "keywords": null, "name": "百世", "parentId": 108902, "remark": null, "updateTime": 1558322493000, "updatedBy": null, "version": 0 }, { "categoryId": 108911, "children": [], "code": null, "createTime": 1558929101000, "createdBy": null, "deleted": false, "description": null, "displayOrder": 1, "enabled": true, "icon": null, "keywords": null, "name": "可乐", "parentId": 108902, "remark": null, "updateTime": 1558929101000, "updatedBy": null, "version": 0 } ], "code": "001", "createTime": 1558322454000, "createdBy": null, "deleted": false, "description": "描述", "displayOrder": 1, "enabled": true, "icon": "", "keywords": null, "name": "饮料", "parentId": 0, "remark": null, "updateTime": 1558322454000, "updatedBy": null, "version": 0 }, { "categoryId": 108905, "children": [ { "categoryId": 108907, "children": [], "code": "03", "createTime": 1558594961000, "createdBy": null, "deleted": false, "description": null, "displayOrder": 2, "enabled": true, "icon": null, "keywords": null, "name": "西瓜", "parentId": 108905, "remark": null, "updateTime": 1558929066000, "updatedBy": null, "version": 1 }, { "categoryId": 108909, "children": [], "code": null, "createTime": 1558929072000, "createdBy": null, "deleted": false, "description": null, "displayOrder": 3, "enabled": true, "icon": null, "keywords": null, "name": "葡萄", "parentId": 108905, "remark": null, "updateTime": 1559039966000, "updatedBy": null, "version": 1 }, { "categoryId": 108910, "children": [], "code": null, "createTime": 1558929080000, "createdBy": null, "deleted": false, "description": null, "displayOrder": 1, "enabled": true, "icon": null, "keywords": null, "name": "柚子", "parentId": 108905, "remark": null, "updateTime": 1558929080000, "updatedBy": null, "version": 0 } ], "code": null, "createTime": 1558505204000, "createdBy": null, "deleted": false, "description": null, "displayOrder": 2, "enabled": true, "icon": null, "keywords": null, "name": "水果", "parentId": 108904, "remark": null, "updateTime": 1559040809000, "updatedBy": null, "version": 2 } ](可能是一个object,可能是一个array),错误的时候返回的是一个 { "code": 404102, "errors": [ { "message": "用户已存在", "reason": "[Unauthorized] - 当前请求未通过授权" } ], "message": "用户已存在" } (话说我们这后台给的是一份json文件,直接在postman里面看的,又没文字描述,找这个error找了好久后才发现在在errorbody里面,想想自己也真是菜) 并且这个错误是不放在返回的body里面,而是返回一个网络错误,放在错误的errorbody里面。 开始也觉得我可能用不到这个库,但是又懒,不想自己封装缓存,cookie那些,然后我修改了作者的 ApiResultFunc类,里面的apply方法, @Override public ApiResult apply(@NonNull ResponseBody responseBody) throws Exception { ApiResult apiResult = new ApiResult<>(); apiResult.setCode(-1); if (type instanceof ParameterizedType) {//自定义ApiResult final Class cls = (Class) ((ParameterizedType) type).getRawType(); if (ApiResult.class.isAssignableFrom(cls)) { final Type[] params = ((ParameterizedType) type).getActualTypeArguments(); final Class clazz = Utils.getClass(params[0], 0); final Class rawType = Utils.getClass(type, 0); try { String json = responseBody.string(); //增加是List判断错误的问题 if (!List.class.isAssignableFrom(rawType) && clazz.equals(String.class)) { apiResult.setData((T) json); apiResult.setCode(0); / final Type type = Utils.getType(cls, 0); ApiResult result = gson.fromJson(json, type); if (result != null) { apiResult = result; apiResult.setData((T) json); } else { apiResult.setMsg("json is null"); }/ } else { if (List.class.isAssignableFrom(rawType)) { JsonArray array = new JsonParser().parse(json).getAsJsonArray(); T t = (T) new ArrayList<>(); for (final JsonElement elem : array) { ((List) t).add(gson.fromJson(elem, clazz)); } apiResult.setData(t); apiResult.setCode(0); } else { ApiResult result = parseCustomApiResult(json, apiResult); if (result != null && result.getCode() == -1) { result.setData(gson.fromJson(result.getCorrectJson(), type)); apiResult = result; result.setCode(0); }else { apiResult.setMsg("json is null"); } }

                }
            } catch (Exception e) {
                e.printStackTrace();
                apiResult.setMsg(e.getMessage());
            } finally {
                responseBody.close();
            }
        } else {
            apiResult.setMsg("ApiResult.class.isAssignableFrom(cls) err!!");
        }
    } else {//默认Apiresult
        try {
            final String json = responseBody.string();
            final Class<T> clazz = Utils.getClass(type, 0);
            if (clazz.equals(String.class)) {
                //apiResult.setData((T) json);
                //apiResult.setCode(0);
                final ApiResult result = parseApiResult(json, apiResult);
                if (result != null) {
                    apiResult = result;
                    apiResult.setData((T) json);
                } else {
                    apiResult.setMsg("json is null");
                }
            } else {
                final ApiResult result = parseApiResult(json, apiResult);
                if (result != null) {
                    apiResult = result;
                    if (apiResult.getData() != null) {
                        T data = gson.fromJson(apiResult.getData().toString(), clazz);
                        apiResult.setData(data);
                    } else {
                        apiResult.setMsg("ApiResult's data is null");
                    }
                } else {
                    apiResult.setMsg("json is null");
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
            apiResult.setMsg(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            apiResult.setMsg(e.getMessage());
        } finally {
            responseBody.close();
        }
    }
    return apiResult;
}

private ApiResult parseCustomApiResult(String json, ApiResult apiResult) throws JSONException {
    if (TextUtils.isEmpty(json))
        return null;
    JSONObject jsonObject = new JSONObject(json);
    if (jsonObject.has("code")) {
        apiResult.setCode(jsonObject.getInt("code"));
        apiResult.setMsg(jsonObject.getString("message"));
    } else {
        apiResult.setCorrectJson(json);
    }

    return apiResult;
}

==============开始我以为错误是在正常的body里面,如果在正常的body里面的话可以修改parseCustomApiResult适配一下自己的数据======

如果错误在errorbody里面的话,是可以在callback的onError里面获取,获取方法其他issue也有提到, public void onError(ApiException e) { LogUtils.e("错误:"+(e==null?"":e.getMessage())); if (e!=null&&e.getCause() instanceof HttpException) { HttpException httpException = (HttpException) e.getCause(); try { // httpException.response().errorBody().string(); LogUtils.e("实际错误:"+(httpException.response().errorBody().string())); } catch (IOException e1) { e1.printStackTrace(); } }

                }

我集成这个库还只有两天,现在还没有真正使用,在数据结构方面可能还会遇到其他坑,但是先用着吧,觉得楼主封装的蛮好的

真正了解库才能体会到价值

zhou-you commented 5 years ago

真正了解库才能体会到价值