【问题标题】:Handling multiple dynamic datatype in JSON在 JSON 中处理多种动态数据类型
【发布时间】:2019-07-01 14:51:15
【问题描述】:

这是用户成功验证时的 JSON 示例

{
    "status": "success",
    "message": "",
    "data": {
        "_id": {
            "$id": "..."
        },
        "email": "...",
        "name": "...",
        "mobile": "...",
        "mobile_status": "...",
        "email_status": "..."
    }
}

当用户凭据错误时

{
    "status": "error",
    "message": {
        "msg": [
            "Login detail incorrect"
        ]
    },
    "data": ""
}

注意messagedata 的数据类型的变化。使用改造配合这个我收到了著名的错误Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

为了解决这个问题,我按照this 示例解决了这个问题。这确实解决了 OBJECT/ARRAY 问题。

我有 3 个模型 LoginResponse,MessageResponse,DataResponse 这就是我试图访问 MessageResponseDataResponse 的方式

我不确定我是否可以使用 2

Gson messageDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
Gson dataDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
builder.addConverterFactory(GsonConverterFactory.create(messageDeserializer));
builder.addConverterFactory(GsonConverterFactory.create(dataDeserializer));

我不认为这些自定义 JsonDeserializer 正在按照它应该的方式工作。我无法从这些 JsonDeserializer 中转换返回的响应。我可以将它们作为字符串访问的唯一方法,它甚至不是正确的 JSON 格式的字符串。

当我访问 LoginResponse 模型时,切换回 .addConverterFactory 的顺序有时会导致崩溃

【问题讨论】:

    标签: android json gson retrofit2


    【解决方案1】:

    您是否有权访问网络错误和响应代码?这样,您可以创建一个明确定义如何反序列化任何响应的 switch 语句

    例如,

    Gson switchToDeserialise(int errorCode){
    
    ///i assume 200 means correct response. And 404 means there's an errorCode
    
    Gson deserializer = new GsonBuilder().create();
    
    switch(errorCode){
    case 200:
    return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
    case 404:
    return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
    default:
    return deserializer;}}
    

    注意:以上代码未经测试。

    ==================================== 真正的崩溃编辑====== ==================================================== ======================

    根据我们的对话,以及我对成功和错误响应的观察,我有这个未经测试的代码/建议:

        //in the retrofit response callback, get the status via JSONObject
    
    JSONObject status = new JSONObject(response.toString()); throws Exception
    String statusString = status.optString("status");
    
    //now take the result of the string to a switch statement
    
    Gson switchToDeserialise(String statusString){
    ///from what you've shown in the success & failure responses, status is either success or error, so...
    
    Gson deserializer = new GsonBuilder().create();
    
    switch(statusString){
    
    case "success":
    return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
    case "error":
    return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
    default:
    return deserializer;
    
    }
    
    }
    

    【讨论】:

    • 响应代码总是(登录成功/失败)200。我可以检测登录成功/失败的唯一方法是查看 JSON 中的成功。如果用户登录成功/失败,我可以使用status 检测,但是当用户登录失败时,我无法使用其模型访问失败消息
    • 好的,我明白了。这里有一个想法:收到响应后,使用JSONObject库请求status的结果,然后制定一个switch语句,定义你的反序列化。
    • 我的错我刚刚意识到我确实有不同的响应代码 200 用于成功登录和 207 用于登录失败。但是如何在 onResponse 方法中传入 Custom CoverterFactory,或者在此之前有没有办法检测响应代码?目前,根据状态成功/错误状态,我正在使用 new Gson().fromJson(data, DataResponse.class); 手动反序列化响应
    • 另外,当登录失败(我在线生成 POJO)时,我在访问 getMsg 方法时得到 nullPointerException(在反序列化器中传递 JSON 后)
    • 如果您使用的是 retrofit,您可以从 Response#code 以及 onResponseonError 方法中获取 errorCode,因此您可以将 switchToDeserialise 方法放在两个调用中背。关于你从 getMsg 得到的 NPE 应该是,IMO,String errorMessage = getMessage().getMsg(0)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    相关资源
    最近更新 更多