Android Gson使用详解

Json 是一种文本形式的数据交换格式,比 xml 更为轻量。Json 的解析和生成的方式很多,在 Android 平台上最常用的类库有 Gson 和 FastJson 两种,这里要介绍的是 Gson

Gson 的 GitHub 主页点击这里:Gson

一、Gson的基本用法

1.1、Gson对象

在进行序列化与反序列操作前,需要先实例化一个 com .google.gson.Gson 对象,获取 Gson 对象的方法有两种

        //通过构造函数来获取
        Gson gson = new Gson();
        //通过 GsonBuilder 来获取,可以进行多项特殊配置
        Gson gson = new GsonBuilder().create();
  • 1
  • 2
  • 3
  • 4

1.2、生成 Json

利用 Gson 可以很方便地生成 Json 字符串,通过使用 addProperty 的四个重载方法

    public static void main(String[] args) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("String", "leavesC");
        jsonObject.addProperty("Number_Integer", 23);
        jsonObject.addProperty("Number_Double", 22.9);
        jsonObject.addProperty("Boolean", true);
        jsonObject.addProperty("Char", 'c');
        System.out.println();
        System.out.println(jsonObject);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

addProperty 方法底层调用的是 add(String property, JsonElement value) 方法,即将基本数据类型转化为了 JsonElement 对象,JsonElement 是一个抽象类,而 JsonObject 继承了 JsonElement ,因此我们可以通过 JsonObject 自己来构建一个 JsonElement

    public static void main(String[] args) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("String", "leavesC");
        jsonObject.addProperty("Number", 23);
        jsonObject.addProperty("Number", 22.9);
        jsonObject.addProperty("Boolean", true);
        jsonObject.addProperty("Char", 'c');

        JsonObject jsonElement = new JsonObject();
        jsonElement.addProperty("Boolean", false);
        jsonElement.addProperty("Double", 25.9);
        jsonElement.addProperty("Char", 'c');
        jsonObject.add("JsonElement", jsonElement);

        System.out.println();
        System.out.println(jsonObject);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

1.3、Json与数组、List的转化

Json数组 与 字符串数组

    public static void main(String[] args) {
        //Json数组 转为 字符串数组
        Gson gson = new Gson();
        String jsonArray = "[\"https://github.com/leavesC\",\"https://www.jianshu.com/u/9df45b87cfdf\",\"Java\",\"Kotlin\",\"Git\",\"GitHub\"]";
        String[] strings = gson.fromJson(jsonArray, String[].class);
        System.out.println("Json数组 转为 字符串数组: ");
        for (String string : strings) {
            System.out.println(string);
        }
        //字符串数组 转为 Json数组
        jsonArray = gson.toJson(jsonArray, new TypeToken<String>() {
        }.getType());
        System.out.println("\n字符串数组 转为 Json数组: ");
        System.out.println(jsonArray);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Json数组 与 List

    public static void main(String[] args) {
        //Json数组 转为 List
        Gson gson = new Gson();
        String jsonArray = "[\"https://github.com/leavesC\",\"https://www.jianshu.com/u/9df45b87cfdf\",\"Java\",\"Kotlin\",\"Git\",\"GitHub\"]";
        List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {
        }.getType());
        System.out.println("\nJson数组 转为 List: ");
        for (String string : stringList) {
            System.out.println(string);
        }
        //List 转为 Json数组
        jsonArray = gson.toJson(stringList, new TypeToken<List<String>>() {
        }.getType());
        System.out.println("\nList 转为 Json数组: ");
        System.out.println(jsonArray);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

1.4、序列化与反序列化

Gson 也提供了 toJson() 和 fromJson() 两个方法用于转化 Model 与 Json,前者实现了序列化,后者实现了反序列化 
首先,声明一个 User 类

/**
 * 作者:chenZY
 * 时间:2018/3/17 18:32
 * 描述:https://github.com/leavesC
 */
public class User {

    private String name;

    private int age;

    private boolean sex;

    public User(String name, int age, boolean sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

序列化的方法很简单,调用 gson 对象的 toJson 方法,传入要序列化的对象

    public static void main(String[] args) {
        //序列化
        User user = new User("leavesC", 24, true);
        Gson gson = new Gson();
        System.out.println();
        System.out.println(gson.toJson(user));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

反序化的方式也类似

    public static void main(String[] args) {
        //反序列化
        String userJson = "{\"name\":\"leavesC\",\"age\":24,\"sex\":true}";
        Gson gson = new Gson();
        User user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

二、属性重命名

继续使用上一节声明的 User 类,根据 User 类声明的各个属性名,移动端的开发者希望接口返回的数据格式即是如下这样的

{"name":"leavesC","age":24,"sex":true}
  • 1

如果没有和服务器端沟通好或者是 API 改版了,接口返回的数据格式可能是这样的

{"Name":"leavesC","age":24,"sex":true}
  • 1
{"userName":"leavesC","age":24,"sex":true}
  • 1

如果继续使用上一节介绍的方法,那无疑会解析出错 
例如

    public static void main(String[] args) {
        //反序列化
        String userJson = "{\"userName\":\"leavesC\",\"age\":24,\"sex\":true}";
        Gson gson = new Gson();
        User user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

name 属性值解析不到,所以为 null 

此时为了兼顾多种格式的数据,就需要使用 SerializedName 注解 
根据 SerializedName 的声明来看,SerializedName 包含两个属性值,一个是字符串,一个是字符串数组,而字符串数组含有默认值

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {
    String value();

    String[] alternate() default {};
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

SerializedName 的作用是为了在序列化或反序列化时,指导 Gson 如果将原有的属性名和其它特殊情况下的属性名联系起来

例如,修改 User 类,为 name 声明 SerializedName 注解,注解值为 userName

/**
 * 作者:chenZY
 * 时间:2018/3/17 18:32
 * 描述:https://github.com/leavesC
 */
public class User {

    @SerializedName("userName")
    private String name;

    private int age;

    private boolean sex;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在序列时,Json 格式就会相应改变

    public static void main(String[] args) {
        //序列化
        User user = new User("leavesC", 24, true);
        Gson gson = new Gson();
        System.out.println();
        System.out.println(gson.toJson(user));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在反序列化时也一样,能够解析到正确的属性值

    public static void main(String[] args) {
        //反序列化
        String userJson = "{\"userName\":\"leavesC\",\"age\":24,\"sex\":true}";
        Gson gson = new Gson();
        User user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

还有个问题没解决,为了应对多种属性名不一致的情况,难道我们要声明多个 User 类吗?这显然是不现实的,所以还需要为 User 类设置多个备选属性名,这就需要用到 SerializedName 注解的另一个属性值 alternate 了。

/**
 * 作者:chenZY
 * 时间:2018/3/17 18:32
 * 描述:https://github.com/leavesC
 */
public class User {

    @SerializedName(value = "userName", alternate = {"user_name", "Name"})
    private String name;

    private int age;

    private boolean sex;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

以下几种情况都能够被正确的反序列化

    public static void main(String[] args) {
        //反序列化
        Gson gson = new Gson();
        String userJson = "{\"userName\":\"leavesC\",\"age\":24,\"sex\":true}";
        User user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);

        userJson = "{\"user_name\":\"leavesC\",\"age\":24,\"sex\":true}";
        user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);

        userJson = "{\"Name\":\"leavesC\",\"age\":24,\"sex\":true}";
        user = gson.fromJson(userJson, User.class);
        System.out.println();
        System.out.println(user);
    }

猜你喜欢

转载自blog.csdn.net/swust_zeng_zhuo_k/article/details/80135653