Gson是谷歌官方推出的json解析工具,Android开发中一般都是使用它,一些主流框架也支持Gson解析,比如我们比较青睐的网络请求框架Okhttp.然而很久没有遇到Gson解析失败的问题了,突然遇到后台返回数据okhttp内部的gson解析失败的问题也是眉头苍蝇,手头又忙,也是折腾了不少时间,在这里记录一下,希望对遇到同样问题的开发者同行有所启发。
新项目中有一个功能接口数据嵌套较复杂,后台返回数据量较大,解析失败后log中也没有明显提示信息,查找起来相当费事。下面来模拟一下类似结构,虽然没有项目中的复杂,只当做演示代码是类似的。
有下面几个java bean:
public class Aaa implements Parcelable {
String name;
protected Aaa(Parcel in) {
name = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Aaa> CREATOR = new Creator<Aaa>() {
@Override
public Aaa createFromParcel(Parcel in) {
return new Aaa(in);
}
@Override
public Aaa[] newArray(int size) {
return new Aaa[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Aaa{" +
"name='" + name + '\'' +
'}';
}
public class Dog implements Parcelable {
String name;
String sex;
Aaa aaa;
protected Dog(Parcel in) {
name = in.readString();
sex = in.readString();
aaa = in.readParcelable(Aaa.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(sex);
dest.writeParcelable(aaa, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Dog> CREATOR = new Creator<Dog>() {
@Override
public Dog createFromParcel(Parcel in) {
return new Dog(in);
}
@Override
public Dog[] newArray(int size) {
return new Dog[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Aaa getAaa() {
return aaa;
}
public void setAaa(Aaa aaa) {
this.aaa = aaa;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", aaa=" + aaa +
'}';
}
}
public class People implements Parcelable {
String name;
int age;
Dog dog;
List<Dog> dogs;
protected People(Parcel in) {
name = in.readString();
age = in.readInt();
dog = in.readParcelable(Dog.class.getClassLoader());
dogs = in.createTypedArrayList(Dog.CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeParcelable(dog, flags);
dest.writeTypedList(dogs);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<People> CREATOR = new Creator<People>() {
@Override
public People createFromParcel(Parcel in) {
return new People(in);
}
@Override
public People[] newArray(int size) {
return new People[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<Dog> getDogs() {
return dogs;
}
public void setDogs(List<Dog> dogs) {
this.dogs = dogs;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
", dog=" + dog +
", dogs=" + dogs +
'}';
}
}
写一个activity来测试:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String json = "{\n" +
"\"name\": \"cui\",\n" +
" \"age\": 6\n" +
"}";
String json1 = "{\n" +
"\"name\": \"cui\"\n" +
"}";
String json2 = "{\n" +
" \"age\": 6\n" +
"}";
String json3 = "{\n" +
" \"age\": 6,\n" +
"\"dogs\":[]\n" +
"}";
String json4="{\n" +
" \"age\": 6,\n" +
"\"dog\":\"\"\n" +
"}";
String json5="{\n" +
" \"age\": 6,\n" +
"\"dog\":{}\n" +
"}";
Gson gson = new Gson();
People people = gson.fromJson(json5,People.class);
Log.e("MainActivity","name:"+people.getName());
Log.e("MainActivity","age:"+people.getAge());
Log.e("MainActivity","dog:"+people.getDog());
Log.e("MainActivity","dogs:"+people.getDogs());
Log.e("MainActivity","people:"+people.toString());
}
测试结果为:
- 在json字符串中包含多余字段时,gson可以解析;
- 在json字符串中缺少某些字段时,gson可以解析,解析成对象后缺少的字段会有缺省值,一般基本数据类型如int为0,对象为null;
- 在json字符串中字段值的类型错误时,gson解析失败.比如
- 例子中的age为int,返回json中{“age”:“6”}会失败;
- 例子中的dog为对象,返回{“dog”:""}或者{“dog”:“{}”}会失败,必须为{“dog”:{}};
- 例子中的dogs为list,返回{“dogs”:""}或者{“dogs”:“{}”}或者{“dogs”:“[]”}会失败,必须为{“dogs”:[]};