gson引发的一场血案

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());


    }

测试结果为:

  1. 在json字符串中包含多余字段时,gson可以解析;
  2. 在json字符串中缺少某些字段时,gson可以解析,解析成对象后缺少的字段会有缺省值,一般基本数据类型如int为0,对象为null;
  3. 在json字符串中字段值的类型错误时,gson解析失败.比如
    1. 例子中的age为int,返回json中{“age”:“6”}会失败;
    2. 例子中的dog为对象,返回{“dog”:""}或者{“dog”:“{}”}会失败,必须为{“dog”:{}};
    3. 例子中的dogs为list,返回{“dogs”:""}或者{“dogs”:“{}”}或者{“dogs”:“[]”}会失败,必须为{“dogs”:[]};
发布了224 篇原创文章 · 获赞 390 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/cui130/article/details/89344488