【问题标题】:Android Dynamic response type RetroftAndroid 动态响应类型 Retroft
【发布时间】:2017-12-20 08:21:14
【问题描述】:

你好我有Json这样的回复

[
    {
        "question": "hhhhh",
        "question_answer": "hhhh ",
        "question_type": "question type",
        "questioner_age": "questioner age",
        "questioner_city": "questioner city",
        "questioner_country": "questioner country",
        "questioner_name": "questioner name",
        "questioner_sex": "questioner sex",
        "comments_allowed": "1",
        "question_id": "63",
        "question_date": "05/08/2017 - 19:33",
        "is_public": "1"
    },
    {
        "question": "hhhh !!",
        "question_answer": "hhhh",
        "question_type": [],
        "questioner_age": [],
        "questioner_city": [],
        "questioner_country": [],
        "questioner_name": "hhhhh",
        "questioner_sex": [],
        "comments_allowed": "1",
        "question_id": "57",
        "question_date": "04/30/2017 - 14:24",
        "is_public": "1"
    }
]

如果该列为 null 将返回一个像这样的数组 "question_type": [], 如果不是将作为字符串返回!

所以我试图在改造时得到这个响应,但我失败了,总是得到这个错误

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 预期 BEGIN_OBJECT 但在第 4 行第 2 列路径 $ 处是 BEGIN_ARRAY

在互联网上搜索后,我尝试了类似的方法,但它不起作用!

    Gson gson = new Gson();
    String json = response.body().toString();


    if (json instanceof String)
    {

    MyQuestionModelString parseObject = gson.fromJson(json, MyQuestionModelString.class);
                apiCallResponse.onSuccess(parseObject,responseMessage);
            }else {
    MyQuestionModel parseObject = gson.fromJson(json, MyQuestionModel.class);
                apiCallResponse.onSuccess(parseObject,responseMessage);
            }

任何帮助!

更新!

这是我的响应模型和同样的错误!!!

public class MyQuestionModel {

    @SerializedName("question")
    @Expose
    private String question;
    @SerializedName("question_answer")
    @Expose
    private String questionAnswer;
    @SerializedName("question_type")
    @Expose
    private List<Object> questionType = null;
    @SerializedName("questioner_age")
    @Expose
    private List<Object> questionerAge = null;
    @SerializedName("questioner_city")
    @Expose
    private List<Object> questionerCity = null;
    @SerializedName("questioner_country")
    @Expose
    private List<Object> questionerCountry = null;
    @SerializedName("questioner_name")
    @Expose
    private String questionerName;
    @SerializedName("questioner_sex")
    @Expose
    private List<Object> questionerSex = null;
    @SerializedName("comments_allowed")
    @Expose
    private String commentsAllowed;
    @SerializedName("question_id")
    @Expose
    private String questionId;
    @SerializedName("question_date")
    @Expose
    private String questionDate;
    @SerializedName("is_public")
    @Expose
    private String isPublic;
}

我的主要问题是如何定义这个字段!问题类型 screen shot

【问题讨论】:

  • 请发布您的型号的代码。
  • Gson解析错误正确创建模型
  • 我在模型中使用了pojo
  • 我更新我的问题请帮忙!

标签: java android json retrofit


【解决方案1】:

在解析json的过程中,如果没有找到SerializedName键,会抛出异常。使用@Expose 让反序列化器知道该字段可以为空。这是您提到的响应的类似模型

public class ResponsePojo {

List<Data> data;

public class Data {
    @Expose
    @SerializedName("question")
    String question;

    @Expose
    @SerializedName("question_answer")
    String questionAnswer;

    @Expose
    @SerializedName("question_type")
    String questionType;

    @Expose
    @SerializedName("questioner_age")
    String questionerAge;

    @Expose
    @SerializedName("questioner_city")
    String questionerCity;

    @Expose
    @SerializedName("questioner_country")
    String questionerCountry;

    @Expose
    @SerializedName("questioner_name")
    String questionerName;

    @Expose
    @SerializedName("questioner_sex")
    String questionerSex;

    @Expose
    @SerializedName("comments_allowed")
    String commentsAllowed;

    @Expose
    @SerializedName("question_id")
    String questionId;

    @Expose
    @SerializedName("question_date")
    String questionDate;

    @Expose
    @SerializedName("is_public")
    String isPublic;
}

}

【讨论】:

  • com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为字符串,但在第 4 行第 1074 列路径 $[1].question_type 处为 BEGIN_ARRAY
【解决方案2】:

您必须使用@Exposed 标签指明模型中的哪些参数或对象是可选的。

示例

    @Expose
    @SerializedName("question_type")
    private String mQuestionType;

【讨论】:

  • 错误是 bcs 它在等待一个数组而不是一个对象,然后像这样定义一个数组:private List&lt;String&gt; mQuestionType;
  • 顺便说一句,更新问题,否则无法知道是哪个问题。
【解决方案3】:

你的问题是

ava.lang.IllegalStateException: 预期为 BEGIN_OBJECT 但在第 4 行第 2 列路径 $

处为 BEGIN_ARRAY
  • 如果你的json码是[...],你的返回是JSONArray,你可以用Gson解析成List&lt;Object&gt;

  • 如果你的json码是{...},你的返回是JSONObject,你可以用Gson解析成Object

所以你应该使用List&lt;MyQuestionModel&gt; 来获取解析后的数据。

将您的呼叫代码中的MyQuestionModel 更改为List&lt;MyQuestionModel&gt;

示例

Call<List<MyQuestionModel>> getData();

还有我的代码。

JSONEntity为你json

public class JSONEntity {

/**
 * question : hhhhh
 * question_answer : hhhh
 * question_type : question type
 * questioner_age : questioner age
 * questioner_city : questioner city
 * questioner_country : questioner country
 * questioner_name : questioner name
 * questioner_sex : questioner sex
 * comments_allowed : 1
 * question_id : 63
 * question_date : 05/08/2017 - 19:33
 * is_public : 1
 */

private String question;
private String question_answer;
private String question_type;
private String questioner_age;
private String questioner_city;
private String questioner_country;
private String questioner_name;
private String questioner_sex;
private String comments_allowed;
private String question_id;
private String question_date;
private String is_public;

public String getQuestion() {
    return question;
}

public void setQuestion(String question) {
    this.question = question;
}

public String getQuestion_answer() {
    return question_answer;
}

public void setQuestion_answer(String question_answer) {
    this.question_answer = question_answer;
}

public String getQuestion_type() {
    return question_type;
}

public void setQuestion_type(String question_type) {
    this.question_type = question_type;
}

public String getQuestioner_age() {
    return questioner_age;
}

public void setQuestioner_age(String questioner_age) {
    this.questioner_age = questioner_age;
}

public String getQuestioner_city() {
    return questioner_city;
}

public void setQuestioner_city(String questioner_city) {
    this.questioner_city = questioner_city;
}

public String getQuestioner_country() {
    return questioner_country;
}

public void setQuestioner_country(String questioner_country) {
    this.questioner_country = questioner_country;
}

public String getQuestioner_name() {
    return questioner_name;
}

public void setQuestioner_name(String questioner_name) {
    this.questioner_name = questioner_name;
}

public String getQuestioner_sex() {
    return questioner_sex;
}

public void setQuestioner_sex(String questioner_sex) {
    this.questioner_sex = questioner_sex;
}

public String getComments_allowed() {
    return comments_allowed;
}

public void setComments_allowed(String comments_allowed) {
    this.comments_allowed = comments_allowed;
}

public String getQuestion_id() {
    return question_id;
}

public void setQuestion_id(String question_id) {
    this.question_id = question_id;
}

public String getQuestion_date() {
    return question_date;
}

public void setQuestion_date(String question_date) {
    this.question_date = question_date;
}

public String getIs_public() {
    return is_public;
}

public void setIs_public(String is_public) {
    this.is_public = is_public;
}
}

以及解析它的代码。

 Gson gson = new Gson();
 String jsonString = response.body().string();
 Type type = new TypeToken<List<JSONEntity>>() {
    }.getType();
 List<JSONEntity> datas = gson.fromJson(jsonString, type);

编辑

如果你的回复是JSONArray,你可以这样试试。

List<JSONEntity> datas = response.body();

【讨论】:

  • 你能解释更多吗!
  • 但是如何检查响应是 [...] 还是 {...} ??
  • 打印String jsonString = response.body().string(); .
  • 好的,现在我遇到了这个错误,预期是一个字符串,但在第 4 行第 1074 列路径 $[1].question_type 处是 BEGIN_ARRAY
  • 你能展示你的整个代码吗?我会更快地为你解决。
【解决方案4】:

尝试更改您的 JSON 结构

第一种方法

如果该列为空返回"question_type": null,否则显示"question_type": "value"

相反

如果该列为空,将返回一个像这样的数组"question_type": []if not will return as a string!

第二种方法不改变Json结构

使用 Gson 处理 Dynamic JSON

试试这个:

你必须使用deserialize来解析json中的动态数据类型

在回复pojo中使用object

例如:

    Call<Object> call = //your API call  ResponsePojo  instead use `Object`
    call.enqueue(new Callback<Object>() 
    {
        @Override
        public void onResponse(Response<Object> response, Retrofit retrofit)
        {

                try {
                    JSONArray jsonArray=new JSONArray(json);
                    for (int i = 0; i < jsonArray.length(); i++) {
                        Gson gson = new GsonBuilder()
                                .registerTypeAdapter(ServerResponse.class, new ServerResponse.OptionsDeserilizer())
                                .create();
                        ServerResponse serverResponse=gson.fromJson(jsonArray.get(i).toString(), ServerResponse.class);
                        System.out.println(serverResponse);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }



        }

        @Override
        public void onFailure(Throwable t) 
        {
         ///Handle failure
        }
    });

将此ServerResponsePojoJsonDeserializer 一起使用

    import android.text.TextUtils;

    import com.google.gson.Gson;
    import com.google.gson.JsonDeserializationContext;
    import com.google.gson.JsonDeserializer;
    import com.google.gson.JsonElement;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParseException;
    import com.google.gson.annotations.Expose;
    import com.google.gson.annotations.SerializedName;
    import com.google.gson.reflect.TypeToken;

    import java.lang.reflect.Type;

    public class ServerResponse {

        @SerializedName("question")
        @Expose
        private String question;
        @SerializedName("question_answer")
        @Expose
        private String questionAnswer;


        private String questionerName;

        @SerializedName("comments_allowed")
        @Expose
        private String commentsAllowed;
        @SerializedName("question_id")
        @Expose
        private String questionId;
        @SerializedName("question_date")
        @Expose
        private String questionDate;
        @SerializedName("is_public")
        @Expose
        private String isPublic;

        public String getQuestion() {
            return question;
        }

        public void setQuestion(String question) {
            this.question = question;
        }

        public String getQuestionAnswer() {
            return questionAnswer;
        }

        public void setQuestionAnswer(String questionAnswer) {
            this.questionAnswer = questionAnswer;
        }


        /* public List<OptionValue> getQuestionerAge() {
             return questionerAge;
         }

         public void setQuestionerAge(List<OptionValue> questionerAge) {
             this.questionerAge = questionerAge;
         }

         public List<OptionValue> getQuestionerCity() {
             return questionerCity;
         }

         public void setQuestionerCity(List<OptionValue> questionerCity) {
             this.questionerCity = questionerCity;
         }

         public List<OptionValue> getQuestionerCountry() {
             return questionerCountry;
         }

         public void setQuestionerCountry(List<OptionValue> questionerCountry) {
             this.questionerCountry = questionerCountry;
         }
     */
        public String getQuestionerName() {
            return questionerName;
        }

        public void setQuestionerName(String questionerName) {
            this.questionerName = questionerName;
        }
    /*
        public List<OptionValue> getQuestionerSex() {
            return questionerSex;
        }

        public void setQuestionerSex(List<OptionValue> questionerSex) {
            this.questionerSex = questionerSex;
        }*/

        public String getCommentsAllowed() {
            return commentsAllowed;
        }

        public void setCommentsAllowed(String commentsAllowed) {
            this.commentsAllowed = commentsAllowed;
        }

        public String getQuestionId() {
            return questionId;
        }

        public void setQuestionId(String questionId) {
            this.questionId = questionId;
        }

        public String getQuestionDate() {
            return questionDate;
        }

        public void setQuestionDate(String questionDate) {
            this.questionDate = questionDate;
        }

        public String getIsPublic() {
            return isPublic;
        }

        public void setIsPublic(String isPublic) {
            this.isPublic = isPublic;
        }

        public class OptionValue {

        }

        public void setQuestionType(String questionType) {
            this.questionType = questionType;
        }

        String questionType;


        public static class OptionsDeserilizer implements JsonDeserializer<ServerResponse> {

            @Override
            public ServerResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                Type listType = new TypeToken<ServerResponse>() {
                }.getType();
                ServerResponse options = (ServerResponse) new Gson().fromJson(json, listType);

                JsonObject jsonArrayValue = json.getAsJsonObject();

                for (int i = 0; i < jsonArrayValue.size(); i++) {
                    JsonObject jsonObject = jsonArrayValue.getAsJsonObject();
                    if (jsonObject.has("question_type")) {
                        JsonElement elem = (JsonElement) jsonObject.get("question_type");
                        if (elem != null && !elem.isJsonNull() && !elem.isJsonArray()) {
                            String valuesString = elem.getAsString();
                            if (!TextUtils.isEmpty(valuesString)) {
                                options.setQuestionType(valuesString);
                            } else {
                                options.setQuestionType("");
                            }

                            //Do your other stuffs
                        }
                    }

                }


                return options;
            }
        }

    }

这是工作愉快的编码

【讨论】:

  • 我无法更改 JSON,所以我会尝试第二种方法,谢谢
  • @mmmaps 我更新了回答你的问题。我尝试了它的工作示例。请试试这个
  • 是的,在 JSON 数组中,您必须提供响应 JSON 字符串 ...例如:response.getbody().tostring()
  • 我做到了,但在模型!在 for 循环中,,, for (int i = 0; i
  • 是 JSON 不是 size length() 你必须使用
猜你喜欢
  • 2021-02-12
  • 1970-01-01
  • 1970-01-01
  • 2016-09-17
  • 2017-11-11
  • 1970-01-01
  • 2020-04-06
  • 2021-12-05
  • 1970-01-01
相关资源
最近更新 更多