【问题标题】:GSON throwing “Expected String but was BEGIN_OBJECT”?GSON 抛出“预期的字符串,但是是 BEGIN_OBJECT”?
【发布时间】:2016-04-06 14:45:10
【问题描述】:

JOSN 数据

{"response":{"status":"ok","userTier":"developer","total":1858191,"startIndex":1,"pageSize":10,"currentPage":1,"pages":185820,"orderBy":"newest","results":[{"type":"article","sectionId":"film","webTitle":"Open thread: what film do you regret watching when you were too young?","webPublicationDate":"2016-04-06T05:34:21Z","id":"film/2016/apr/06/open-thread-what-film-do-you-regret-watching-when-you-were-too-young","webUrl":"http://www.theguardian.com/film/2016/apr/06/open-thread-what-film-do-you-regret-watching-when-you-were-too-young","apiUrl":"http://content.guardianapis.com/film/2016/apr/06/open-thread-what-film-do-you-regret-watching-when-you-were-too-young","sectionName":"Film"},{"type":"article","sectionId":"travel","webTitle":"Sarajevo city guide: 10 of the best art and design-inspired destinations","webPublicationDate":"2016-04-06T05:30:29Z","id":"travel/2016/apr/06/sarajevo-city-guide-10-best-art-design-inspired-destinations","webUrl":"http://www.theguardian.com/travel/2016/apr/06/sarajevo-city-guide-10-best-art-design-inspired-destinations","apiUrl":"http://content.guardianapis.com/travel/2016/apr/06/sarajevo-city-guide-10-best-art-design-inspired-destinations","sectionName":"Travel"}]}}

改造 2.0 调用

addNewUser.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Intent intent = new Intent(getApplicationContext(), ActivityNewUser.class);
            //startActivity(intent);


            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://content.guardianapis.com/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            APIService service = retrofit.create(APIService.class);

            Call<MyResponse> call = service.getNewsData();
            call.enqueue(new Callback<MyResponse>() {
                @Override
                public void onResponse(Call<MyResponse> call1, Response<MyResponse> response) {
                    if (response.isSuccess()) {
                        Toast.makeText(getApplicationContext(), "success", Toast.LENGTH_LONG).show();
                    }
                    else{
                        Toast.makeText(getApplicationContext(), "onResponse  - something wrong" + response.message(), Toast.LENGTH_LONG).show();
                    }
                    // Get result Repo from response.body()
                }

                @Override
                public void onFailure(Call<MyResponse> call1, Throwable t) {
                    Toast.makeText(getApplicationContext(), "exception: " + t.getMessage(), Toast.LENGTH_LONG).show();
                }
            });


        }
    });

MyResponse 类:

public class MyResponse {
        String response;

        public String getResponse() {
            return response;
        }

        public void setResponse(String response) {
            this.response = response;
        }
    }

通过异常进行改造调用:“预期字符串但为 BEGIN_OBJECT”?

谁能帮助我为什么会出现这个异常?如何解决?

编辑:

我像这样更改了 myResonse 类:

public class MyResponse {
        @Expose
        @SerializedName("status")
        String status;
        List<Result> results;


        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        public List<Result> getResults() {
            return results;
        }

        public void setResults(List<Result> results) {
            this.results = results;
        }
    }

结果类:

public class Result {

        String type;
        String sectionId;
        String webTitle;
        String webPublicationDate;
        String id;
        String webUrl;
        String apiUrl;
        String sectionName;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getSectionId() {
            return sectionId;
        }

        public void setSectionId(String sectionId) {
            this.sectionId = sectionId;
        }

        public String getWebTitle() {
            return webTitle;
        }

        public void setWebTitle(String webTitle) {
            this.webTitle = webTitle;
        }

        public String getWebPublicationDate() {
            return webPublicationDate;
        }

        public void setWebPublicationDate(String webPublicationDate) {
            this.webPublicationDate = webPublicationDate;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getWebUrl() {
            return webUrl;
        }

        public void setWebUrl(String webUrl) {
            this.webUrl = webUrl;
        }

        public String getApiUrl() {
            return apiUrl;
        }

        public void setApiUrl(String apiUrl) {
            this.apiUrl = apiUrl;
        }

        public String getSectionName() {
            return sectionName;
        }

        public void setSectionName(String sectionName) {
            this.sectionName = sectionName;
        }
    }

和改造电话:

call.enqueue(new Callback<MyResponse>() {
                @Override
                public void onResponse(Call<MyResponse> call1, Response<MyResponse> response) {
                    if (response.isSuccess()) {

                        MyResponse myResponse = response.body();
                        Toast.makeText(getApplicationContext(), "" + myResponse.getResults().size(), Toast.LENGTH_LONG).show();


                    }
                    else{
                        Toast.makeText(getApplicationContext(), "onResponse  - something wrong" + response.message(), Toast.LENGTH_LONG).show();
                    }
                    // Get result Repo from response.body()
                }

                @Override
                public void onFailure(Call<MyResponse> call1, Throwable t) {
                    Toast.makeText(getApplicationContext(), "exception: " + t.getMessage(), Toast.LENGTH_LONG).show();
                }
            });

在这一行给出空指针异常。

 Toast.makeText(getApplicationContext(), "" + myResponse.getResults().size(), Toast.LENGTH_LONG).show();

如何解决。

【问题讨论】:

    标签: android gson retrofit2


    【解决方案1】:

    只需像下面这样创建一个Response 类并使用GSON 进行解析

    public class Response {
    
            @Expose
            @SerializedName("status")
            String status;
    
            public String getstatus() {
                 return this.status;
              }
    
            public void setstatus(String status) {
                this.status = status;
            }
    
            @Expose
            public List<Result> results = new ArrayList<Result>();
    
            public  List<Result> getResults () {
                return results ;
            }
    
            public void setResults(ArrayList<Result> results ) {
                 this.results = results ;
            }
    
            //Make getter and setter for each and every fields in your JSON that you want
    
    }
    

    因为resultsJSONArray 在您的JSON 中,所以您必须将Result 作为另一个模型并添加到主类中,例如

    public class Result{
    
            @Expose
            @SerializedName("type")
            String type;
    
            public String gettype() {
                 return this.type;
              }
    
            public void settype(String type) {
                this.type= type;
            }
    
            //Make getter and setter for each and every fields in your JSON that you want
    
    }
    

    【讨论】:

    • 感谢您的快速回复。根据您的建议,我进行了更改。请参阅帖子中的编辑。虽然 isSuccess() 现在是真的。它在解析后为字段提供空指针异常。我还缺少什么吗?
    • 再次感谢。我尝试了您建议的更改。崩溃现在消失了,但 myResponse.getResults().size() 为 0。我尝试打印 myResponse.getstatus() 值。这是值也是空的。我还缺少什么吗?
    • @DeveshAgrawal 你离得很近。让我仔细检查一下你漏掉了什么
    • 您应该在Response class 中的List&lt;Result&gt; 之前添加@Expose,并发布您新更新的ResultResponse 课程
    • @Expose before List 已经存在于响应类中。同样,到目前为止,我对您发布的两个类都使用相同的代码。
    【解决方案2】:

    MyResponse 包含一个 STRING 类型的响应,而在 JSON 输出中,响应应该是一个对象。您必须创建自定义模型来解决此问题。

    public class ResponseWrapper {
    
    @SerializedName("response")
    @Expose
    private Response response; // There is a Custom Response Model
    
    public Response getResponse() {
    return response;
    }
    
    public void setResponse(Response response) {
    this.response = response;
    }
    }
    

    现在,使用 ResponseWrapper 代替 MyResponse。你的响应模型应该是这样的:

    public class Response {
    
    @SerializedName("status")
    @Expose
    private String status;
    @SerializedName("userTier")
    @Expose
    private String userTier;
    .
    .
    .
    .
    // Write the rest of the entities
    }
    

    编辑

    改变你的方法

    public List<Result> getResults() {
            return results;
    }
    

    收件人:

    public ArrayList<Result> getResults() {
      return results == null ? new ArrayList<>() : results;
    }
    

    如果使用片段或 ACTIVITYNAME.this,则将 getApplicationContext() 更改为 getActivity(),例如:

    Toast.makeText(getActivity(), "" + myResponse.getResults().size(), Toast.LENGTH_LONG).show();
    

    【讨论】:

    • 感谢您的快速回复。根据您的建议,我进行了更改。请参阅帖子中的编辑。虽然 isSuccess() 现在是真的。它在解析后为字段提供空指针异常。我还缺少什么吗?
    猜你喜欢
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多