zoukankan      html  css  js  c++  java
  • HOW TO FIX "EXPECTED BEGIN_ARRAY BUT WAS BEGIN_OBJECT" IN RETROFIT ?

    https://www.freshbytelabs.com/2018/05/how-to-fix-expected-beginarray-but-was.html

    HOW TO FIX "EXPECTED BEGIN_ARRAY BUT WAS BEGIN_OBJECT" IN RETROFIT ?

     
    Before we begin, keep this in mind

    begin_array means the json response is an array which will look something like this [{},{},..]
    begin_object means the json response is an object which will look something like this {....}

    gson is one cool library that will provide us with cool tips in the form of errors while handling json responses. One such tip is "expected begin_array but was begin_object". These tips/errors are quite self explanatory, we can now look deeper into these errors.

    While handling responses using retrofit, we often tend to come across an error "expected begin_array but was begin_object", which is thrown by gsonObviously this means that we are trying to parse the response as if it is a json array response but when actually it is a json object response. But still we come across these errors a lot of time. We will be looking in detail about such situations in this post.

    First add the following dependencies in your app's build.gradle file

    compile 'com.squareup.retrofit2:retrofit:2.3.0' 
    compile 'com.squareup.retrofit2:converter-gson:2.3.0' 

    PARSING JSON OBJECT RESPONSES : 

    • A  json object  response is of the form {....}.  The json object may also contain a json array like the below example where the json object contains a json array named user_array.
    { 
    "username":"jon",
    "email":"jon@email.com", 
    "user_array": [
     { 
     "user_address":"jon",
     "user_location":"jon@email.com"
     }, {..},
     .
     . 
     ]
    }
    


    In order to parse the above json object you can either use the JsonObject from gson or create pojo classes

    1. PARSING USING JSONOBJECT  FROM GSON



    Retrofit retrofit = new Retrofit.Builder() .baseUrl("base_url") .addConverterFactory(GsonConverterFactory.create()) .build(); RequestInterface request = retrofit.create(RequestInterface.class); Call<JsonObject> call=request.getJson(); call.enqueue(new Callback<JsonObject>() { @Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { progressDialog.dismiss(); String s= String.valueOf(response.get("username")); JsonArray user_array= response.getAsJsonArray("user_array"); Toast.makeText(PrintTicket.this,response.toString(),Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<JsonObject> call, Throwable t) { progressDialog.dismiss(); Toast.makeText(PrintTicket.this,t.toString(),Toast.LENGTH_SHORT).show(); } });
    RequestInterface.java
    public interface RequestInterface { @GET("api_endpoint") Call<JsonObject> getJson(); }

    2. PARSING USING POJO  CLASS

    You can automatically generate the pojo classes by pasting your json response structure in http://www.jsonschema2pojo.org/ .
     
    FYI : after pasting the response structure in http://www.jsonschema2pojo.org/ ,  set the source type to JSON and Annotation style to Gson , now click preview button and you can see generated pojo class/classes
     
    For the above case you will need to generate two classes like below
     
    Example.java
     
    public class Example {
    
    @SerializedName("username")
    @Expose
    private String username;
    @SerializedName("email")
    @Expose
    private String email;
    @SerializedName("user_array")
    @Expose
    private List<UserArrayuserArray null;
    
    public String getUsername() {
    return username;
    }
    
    public void setUsername(String username) {
    this.username username;
    }
    
    public String getEmail() {
    return email;
    }
    
    public void setEmail(String email) {
    this.email email;
    }
    
    public List<UserArraygetUserArray() {
    return userArray;
    }
    
    public void setUserArray(List<UserArrayuserArray) {
    this.userArray userArray;
    }
    
    }
     
    UserArray.java
     
    public class UserArray {
    
    @SerializedName("user_address")
    @Expose
    private String userAddress;
    @SerializedName("user_location")
    @Expose
    private String userLocation;
    
    public String getUserAddress() {
    return userAddress;
    }
    
    public void setUserAddress(String userAddress) {
    this.userAddress userAddress;
    }
    
    public String getUserLocation() {
    return userLocation;
    }
    
    public void setUserLocation(String userLocation) {
    this.userLocation userLocation;
    }
    
    }
     
    In the above  pojo classes, we have used @SerializedName annotation which will help us to map the class variables to respective keys in the response json. For example, in UserArray.java, the string variable userAddress is correctly mapped to user_address by using the @SerializedName annotation like this

    @SerializedName("user_address")
    @Expose
    private String userAddress;
    


    The Example.java is for parsing the outer json object whereas UserArray.java is for parsing the inner json object which should be parsed as a list(since there is a list of objects in user_array)
     
     
    Now the retrofit call should be made like the following

    ArrayList<RouteStop> user_array;
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("base_url")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    
    RequestInterface request = retrofit.create(RequestInterface.class);
    Call<Example> call=request.getJson();
    call.enqueue(new Callback<Example>() {
        @Override    
        public void onResponse(Call<Example> call, Response<Example> response) {
            progressDialog.dismiss();
            String user_name= response.getUsername();
            user_array= new ArrayList<>(response.getUserArray());
            Toast.makeText(PrintTicket.this,response.toString(),Toast.LENGTH_SHORT).show();
        }
    
        @Override    
        public void onFailure(Call<Example> call, Throwable t) {
            progressDialog.dismiss();
            Toast.makeText(PrintTicket.this,t.toString(),Toast.LENGTH_SHORT).show();
        }
    });
    

    RequestInterface.java
    public interface RequestInterface {
    @GET("api_endpoint")
    Call<Example> getJson();
    }
    
    
    The error "expected begin_array but was begin_object" occurs  if you are trying to parse the above response using Call<List<Example>> call=request.getJson(); because by using <List<Example>> we are clearly making an array request but we need to make an object request since response is of the form {..}
     
    Similarly we get the error "expected begin_object but was begin_array"  when we are trying to make an object request were the response is of the form [{},{},..]. In such case we should make the call like Call<List<Example>>
     
     
     
     

    RELATED POSTS:

  • 相关阅读:
    selenium—用NoSuchElementException异常判断页面元素是否存在
    CentOS7 Nginx安装及配置反向代理
    CentOS7 安装 jexus-5.8.2-x64
    Windows Server 2008 R2远程协助选项 灰色
    IIS8.5 Error Code 0x8007007e HTTP 错误 500.19的解决方法
    记一次 windows server 2012R2 上安装 MSSQL2005 及网站发布
    记一次《系统集成实施的相关知识》培训自己感悟
    MySql 远程连接的条件
    CentOS7 下安装mysql历程
    VirtualBox虚拟机网络设置(四种方式)
  • 原文地址:https://www.cnblogs.com/rsapaper/p/9888076.html
Copyright © 2011-2022 走看看