Jez*_*spo 71 java android json gson retrofit
我是JSON解析的新手,我正在使用Square的Retrofit库并遇到了这个问题.
我正在尝试解析这个JSON响应:
[
{
"id": 3,
"username": "jezer",
"regid": "oiqwueoiwqueoiwqueoiwq",
"url": "http:\/\/192.168.63.175:3000\/users\/3.json"
},
{
"id": 4,
"username": "emulator",
"regid": "qwoiuewqoiueoiwqueoq",
"url": "http:\/\/192.168.63.175:3000\/users\/4.json"
},
{
"id": 7,
"username": "test",
"regid": "ksadqowueqiaksj",
"url": "http:\/\/192.168.63.175:3000\/users\/7.json"
}
]
Run Code Online (Sandbox Code Playgroud)
这是我的模特:
public class Contacts {
public List<User> contacts;
}
Run Code Online (Sandbox Code Playgroud)
...
public class User {
String username;
String regid;
@Override
public String toString(){
return(username);
}
}
Run Code Online (Sandbox Code Playgroud)
我的界面:
public interface ContactsInterface {
@GET("/users.json")
void contacts(Callback<Contacts> cb);
}
Run Code Online (Sandbox Code Playgroud)
我的成功方法:
@Override
public void success(Contacts c, Response r) {
List<String> names = new ArrayList<String>();
for (int i = 0; i < c.contacts.size(); i++) {
String name = c.contacts.get(i).toString();
Log.d("Names", "" + name);
names.add(name);
}
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, names);
mSentTo.setAdapter(spinnerAdapter);
}
Run Code Online (Sandbox Code Playgroud)
当我在成功方法上使用它时会抛出错误
预期BEGIN_OBJECT但在第1行第2列是BEGIN_ARRAY
这有什么不对?
Jak*_*ton 149
现在,您正在解析响应,就像它的格式如下:
{
"contacts": [
{ .. }
]
}
Run Code Online (Sandbox Code Playgroud)
例外情况告诉您,您希望根目录中有一个对象,但实际数据实际上是一个数组.这意味着您需要将类型更改为数组.
最简单的方法是在回调中使用列表作为直接类型:
@GET("/users.json")
void contacts(Callback<List<User>> cb);
Run Code Online (Sandbox Code Playgroud)
dependencies used :
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
Run Code Online (Sandbox Code Playgroud)
json响应可以是array response或,object response甚至可以是两者的组合。请参阅以下三种情况
Case 1 : Parsing a json array response (OP案)
这种情况适用于以下json responses形式[{...} ,{...}]
例如
[
{
"id": 3,
"username": "jezer",
"regid": "oiqwueoiwqueoiwqueoiwq",
"url": "http:\/\/192.168.63.175:3000\/users\/3.json"
},
.
.
]
Run Code Online (Sandbox Code Playgroud)
首先为此数组创建一个模型类,或者只是转到jsonschema2pojo并自动生成如下所示的模型类
Contacts.java
public class Contacts {
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("username")
@Expose
private String username;
@SerializedName("regid")
@Expose
private String regid;
@SerializedName("url")
@Expose
private String url;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRegid() {
return regid;
}
public void setRegid(String regid) {
this.regid = regid;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Run Code Online (Sandbox Code Playgroud)
ContactsInterface
在这种情况下,您应该返回如下对象列表
public interface ContactsInterface {
@GET("/users.json")
Call<List<Contacts>> getContacts();
}
Run Code Online (Sandbox Code Playgroud)
然后retrofit2像下面这样拨打电话
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("baseurl_here")
.addConverterFactory(GsonConverterFactory.create())
.build();
ContactsInterface request = retrofit.create(ContactsInterface.class);
Call<List<Contacts>> call = request.getContacts();
call.enqueue(new Callback<List<Contacts>>() {
@Override
public void onResponse(Call<List<Contacts>> call, Response<List<Contacts>> response) {
Toast.makeText(MainActivity.this,response.body().toString(),Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<List<Contacts>> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
Run Code Online (Sandbox Code Playgroud)
response.body() 将为您提供对象列表
您还可以检查以下两种情况以供参考
Case 2 : Parsing a json object response
这种情况适用于格式为{..}的json响应
例如
{
"id": 3,
"username": "jezer",
"regid": "oiqwueoiwqueoiwqueoiwq",
"url": "http:\/\/192.168.63.175:3000\/users\/3.json"
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们与object上面的示例相同。因此,模型类将是相同的,但是像上面的示例一样,我们没有这些对象的数组-只有一个对象,因此我们不需要将其解析为列表。
因此,对于 object response
public interface ContactsInterface {
@GET("/users.json")
Call<Contacts> getContacts();
}
Run Code Online (Sandbox Code Playgroud)
然后retrofit2像下面这样拨打电话
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("baseurl_here")
.addConverterFactory(GsonConverterFactory.create())
.build();
ContactsInterface request = retrofit.create(ContactsInterface.class);
Call<Contacts> call = request.getContacts();
call.enqueue(new Callback<Contacts>() {
@Override
public void onResponse(Call<Contacts> call, Response<Contacts> response) {
Toast.makeText(MainActivity.this,response.body().toString(),Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<Contacts> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
Run Code Online (Sandbox Code Playgroud)
response.body() 会给你对象
您还可以在解析json对象响应时检查一个常见错误:“预期的begin_array但为begin_object”
Case 3 : Parsing a json array inside json object
这种情况适用于以下json responses形式{"array_name":[{...} ,{...}]}
例如
{
"contacts":
[
{
"id": 3,
"username": "jezer",
"regid": "oiqwueoiwqueoiwqueoiwq",
"url": "http:\/\/192.168.63.175:3000\/users\/3.json"
}
]
}
Run Code Online (Sandbox Code Playgroud)
您将需要两个模型类,因为我们有两个对象(数组外一个,数组内一个)。
ContactWrapper
public class ContactWrapper {
@SerializedName("contacts")
@Expose
private List<Contacts> contacts = null;
public List<Contacts> getContacts() {
return contacts;
}
public void setContacts(List<Contacts> contacts) {
this.contacts = contacts;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将Contacts.java上面生成的用于列表对象(针对情况1生成)
因此,对于 object response
public interface ContactsInterface {
@GET("/users.json")
Call<ContactWrapper> getContacts();
}
Run Code Online (Sandbox Code Playgroud)
然后retrofit2像下面这样拨打电话
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("baseurl_here")
.addConverterFactory(GsonConverterFactory.create())
.build();
ContactsInterface request = retrofit.create(ContactsInterface.class);
Call<ContactWrapper> call = request.getContacts();
call.enqueue(new Callback<ContactWrapper>() {
@Override
public void onResponse(Call<ContactWrapper> call, Response<ContactWrapper> response) {
Toast.makeText(MainActivity.this,response.body().getContacts().toString(),Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<ContactWrapper> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
Run Code Online (Sandbox Code Playgroud)
在这里,与案例1的区别在于我们应该使用response.body().getContacts()而不是response.body()获取对象列表
以上案例的一些参考资料:
情况1:解析json数组响应,情况2:解析json对象响应,混合:在另一个json对象中解析json数组
小智 8
在你的界面替换
@GET("/users.json")
void contacts(Callback<Contacts> cb);
Run Code Online (Sandbox Code Playgroud)
通过这段代码
@GET("/users.json")
void contacts(Callback<List<Contacts>> cb);
Run Code Online (Sandbox Code Playgroud)