0

hello i have Json response like this

[
    {
        "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"
    }
]

if the column is null will return as an array like this "question_type": [], if not will return as a string !

so i tried to get this response on retrofit but i failed and always got this error

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 4 column 2 path $

after i searched in the internet i tried something like this but its not working !!

    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);
            }

any help !

UPDATAE !

this is my model for this response and same error !!!

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;
}

My Main issue that how to define this field ! question_type screen shot

mmm aps
  • 21
  • 6

4 Answers4

0

You problem is

ava.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 4 column 2 path $

  • If your json code is [...],your return is JSONArray , you can use Gsonto parse it to List<Object> .

  • If your json code is {...},your return is JSONObject , you can use Gsonto parse it to Object .

So you should use List<MyQuestionModel> to get parsed data .

Change MyQuestionModel to List<MyQuestionModel> in your call code .

Sample

Call<List<MyQuestionModel>> getData();

And my code for doing it .

JSONEntity for you 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;
}
}

And the code for parse it .

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

EDIT

If your response is JSONArray , you can try like this .

List<JSONEntity> datas = response.body();
KeLiuyue
  • 8,149
  • 4
  • 25
  • 42
  • can u explain more ! – mmm aps Dec 20 '17 at 08:31
  • but how to check if response is [...] or {...} ?? – mmm aps Dec 20 '17 at 08:43
  • Just print `String jsonString = response.body().string();` . – KeLiuyue Dec 20 '17 at 08:45
  • ok now i have this error ,, Expected a string but was BEGIN_ARRAY at line 4 column 1074 path $[1].question_type – mmm aps Dec 20 '17 at 09:04
  • Could you show your whole code about it ?And i will more quickly solve for you . – KeLiuyue Dec 20 '17 at 09:05
  • how i can check if response is array or string ?? – mmm aps Dec 20 '17 at 09:31
  • if your response return is start with `[` ,It was `JSONArray` .If your response return is start with `"` , it was `String` – KeLiuyue Dec 20 '17 at 10:07
  • @mmmaps check the length of value you got in question_type. if its greater than 0 than it contains data hence its a String else Array. – beginner Dec 20 '17 at 10:08
  • still cannot solve this issue ,, do you have another idea?? for this ?? please tell me !! – mmm aps Dec 21 '17 at 10:22
  • You can check ( https://stackoverflow.com/questions/9598707/gson-throwing-expected-begin-object-but-was-begin-array)[https://stackoverflow.com/questions/9598707/gson-throwing-expected-begin-object-but-was-begin-array] and (https://stackoverflow.com/questions/39161354/gson-array-error-message-expected-a-string-but-was-begin-array)[https://stackoverflow.com/questions/39161354/gson-array-error-message-expected-a-string-but-was-begin-array] – KeLiuyue Dec 22 '17 at 00:31
  • Change MyQuestionModel to List in your call code . – KeLiuyue Dec 23 '17 at 02:40
  • Your using org.json imported so try to use gson.json – Ramesh sambu Dec 24 '17 at 13:43
0

Try to change your JSON Structure

First Approach

To

If the column is null return "question_type": null,else show "question_type": "value"

Instead

If the column is null will return as an array like this "question_type": [], if not will return as a string!

Second Approach Without changing Json structure

Handling Dynamic JSON Using Gson

Try this:

You have to use deserialize to parse dynamic datatype in json

In the reponse pojo use object

Ex:

    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
        }
    });

Use this ServerResponsePojo with JsonDeserializer

    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;
            }
        }

    }

This is working happy codeing

Ramesh sambu
  • 3,577
  • 2
  • 24
  • 39
0

During the parsing of json if the SerializedName key is not found it will throw an exception. Use @Expose to let the deserializer to know that this field can be null. Here is a similar Model of your mentioned response

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: Expected a string but was BEGIN_ARRAY at line 4 column 1074 path $[1].question_type – mmm aps Dec 20 '17 at 09:10
0

You must indicate which paramters or objects in the model are optional with @Exposed tag.

Example

    @Expose
    @SerializedName("question_type")
    private String mQuestionType;
Ana
  • 11
  • 2
  • The error is bcs it's waiting an array rather than an Object, then define an array like this: `private List mQuestionType;` – Ana Dec 22 '17 at 09:33
  • and btw, update the question then otherwise is imposible to know which is the problem. – Ana Dec 22 '17 at 12:24