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 ?

MAY 09, 2018 / BY NAVNEET KRISHNA / IN BEGIN_ARRAYBEGIN_OBJECTEXPECTED BEGIN_ARRAY BUT WAS BEGIN_OBJECTGSONJSON ARRAYJSON OBJECTNAVNEETPOJORETROFIT / WITH NO COMMENTS / 

 
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<UserArray> userArray = 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<UserArray> getUserArray() {
return userArray;
} public void setUserArray(List<UserArray> userArray) {
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:

HOW TO FIX "EXPECTED BEGIN_ARRAY BUT WAS BEGIN_OBJECT" IN RETROFIT ?的更多相关文章

  1. Expected BEGIN_ARRAY but was BEGIN_OBJECT

    Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 3519 path $.data[1].inspector_user Gson 中 ...

  2. 利用Retrofit, RxJava获取网络内容

    Retrofit & RxJava 关于如何使用Retrofit和RxJava请阅读参考中的两篇文章. Retrofit处理数据 Retrofit是在什么时候处理从网络中获取到的json数据的 ...

  3. realm怎样支持hashmap

    realm不支持hashmap这种形式stackoverflow给出了解决方案http://stackoverflow.com/ques... class MyData extends RealmOb ...

  4. Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path 解决办法

    返回数据解析错误 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT ...

  5. gson Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path

    返回数据解析错误 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT ...

  6. Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2

    原因是解析的时候多了,逗号,或是 \ 解决方法:一 revJson=revJson.replace("\\", "");//去掉'/' revJson=revJ ...

  7. ERROR 3009 (HY000): Column count of mysql.user is wrong. Expected 45, found 42. Created with MySQL 50560, now running 50725. Please use mysql_upgrade to fix this error.

    centos7.5 登入mysql,进行授权报错 问题: mysql> grant all privileges on *.* to 'lvhanzhi'@'%' identified by ' ...

  8. Column count of mysql.user is wrong. Expected 43, found 42. Created with MySQL 50518, now running 50641. Please use mysql_upgrade to fix this error.

    出现问题: Column count of mysql.user is wrong. Expected 43, found 42. Created with MySQL 50518, now runn ...

  9. [React] Fix "React Error: Rendered fewer hooks than expected"

    In this lesson we'll see an interesting situation where we're actually calling a function component ...

随机推荐

  1. gdb,程序调试助手

    启动GDB:(其中我的app是编译之后的可执行文件) 退出命令:quit或者简写q 帮助获取: gdb通过完备的在线帮助,使我们使用起来更加方便.所有的帮助信息都是通过help命令获得的,运行help ...

  2. Mysql定时备份数据脚本

    项目集群搭建完成,数据库虽有做主从同步,但考虑到数据安全性,为了满足这个需求那么要每天对数据备份处理, 但每天手动进行备份处理太过于被动,而且白天用户访问,会有数据变化以及在备份时会影响服务器正常运行 ...

  3. Parallelism , Partitioner

    转:spark通过合理设置spark.default.parallelism参数提高执行效率 spark中有partition的概念(和slice是同一个概念,在spark1.2中官网已经做出了说明) ...

  4. Spider Studio 新版本 (20140225) - 设置菜单调整 / 提供JQueryContext布局相关的方法

    这是年后的第一个新版本, 包含如下: 1. 先前去掉的浏览器设置功能又回来了! 说来惭愧, 去掉了这两个功能之后发现浏览经常会被JS错误打断, 很不方便, 于是乎又把它们给找回来了. :) 2. 为J ...

  5. C#中利用JQuery实现视频网站的缩略图采集

    最近有朋友想要采集优酷的视频标题和缩略图 (哈哈, 并非商业目的). 找到我帮忙, 考虑到有我刚刚发布的SpiderStudio, 我毫不犹豫的答应了. 首先在网页上视频的基本结构为: div.v - ...

  6. 设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就 ...

  7. div允许用户输入

    主要是用到contenteditable属性,就可以用div让用户输入了 <div id="guo" style="width:500px; height:200p ...

  8. PHP多进程编程(一)

    虽然PHP 中,多进程用的比较的少.但是毕竟可能是会用到了.我最近就遇到这样一个问题,用户提交几百个url以后,要读出这个url 中的标题. 当然,你不希望用户等待的太久,10s 钟应该给出个答案.但 ...

  9. 专题实验 Toad 用户的创建与管理( 包括 role 等 )

    1. 用户登录数据库 是否可以通过操作系统权限来登录数据库, $ORACLE_HOME/network/admin/sqlnet.ora 这个文件中设置, 如果增加参数sqlnet.authentic ...

  10. CSS3 实现厉害的文字和输入框组合效果

    最近在忙着弄网站,学到了不少效果,这又是一个厉害的  <html> <head> <meta http-equiv="Content-Type" co ...