Android Gson使用详解,android开发基础书

本文详细介绍了Android中Gson库的使用,包括基本用法如创建Gson对象、生成Json,以及Json与数组、List的转化。还深入讨论了属性重命名、字段过滤的各种策略,如基于@Expose注解、版本控制、访问修饰符和自定义策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Gson 的 GitHub 主页点击这里:Gson

一、Gson的基本用法

1.1、Gson对象

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

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

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

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

ject.addProperty(“Boolean”, true);
jsonObject.addProperty(“Char”, ‘c’);
System.out.println();
System.out.println(jsonObject);
}

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.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() {
}.getType());
System.out.println(”\n字符串数组 转为 Json数组: ");
System.out.println(jsonArray);
}

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 stringList = gson.fromJson(jsonArray, new TypeToken<List>() {
}.getType());
System.out.println("\nJson数组 转为 List: “);
for (String string : stringList) {
System.out.println(string);
}
//List 转为 Json数组
jsonArray = gson.toJson(stringList, new TypeToken<List>() {
}.getType());
System.out.println(”\nList 转为 Json数组: ");
System.out.println(jsonArray);
}

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 +
‘}’;
}

}

序列化的方法很简单,调用 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));
}

反序化的方式也类似

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

二、属性重命名

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

{“name”:“leavesC”,“age”:24,“sex”:true}

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

{“Name”:“leavesC”,“age”:24,“sex”:true}

{“userName”:“leavesC”,“age”:24,“sex”:true}

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

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

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

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

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

String[] alternate() default {};
}

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;

}

在序列时,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));
}

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

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

还有个问题没解决,为了应对多种属性名不一致的情况,难道我们要声明多个 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;

}

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

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

三、字段过滤

有时候并不是所有的字段都需要进行系列化和反序列化,因此需要对某些字段进行排除,有四种方法可以来实现这种需求。

3.1、基于@Expose注解

Expose 注解包含两个属性值,且均声明了默认值。Expose 的含义即为“暴露”,即用于对外暴露字段,serialize 用于指定是否进行序列化,deserialize 用于指定是否进行反序列化。如果字段不声明 Expose 注解,则意味着不进行序列化和反序列化操作,相当于两个属性值均为 false 。此外,Expose 注解需要和 GsonBuilder 构建的 Gson 对象一起使用才能生效。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Expose {
boolean serialize() default true;

boolean deserialize() default true;
}

Expose 注解的注解值声明情况有四种

@Expose(serialize = true, deserialize = true) //序列化和反序列化都生效
@Expose(serialize = false, deserialize = true) //序列化时不生效,反序列化时生效
@Expose(serialize = true, deserialize = false) //序列化时生效,反序列化时不生效
@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不写注解一样

现在来看个例子,修改 User 类

/**

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

@Expose(serialize = true, deserialize = true) //序列化和反序列化都生效
private String a;

@Expose(serialize = false, deserialize = true) //序列化时不生效,反序列化时生效
private String b;

@Expose(serialize = true, deserialize = false) //序列化时生效,反序列化时不生效
private String c;

@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不写注解一样
private String d;

private String e;

public User(String a, String b, String c, String d, String e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}

@Override
public String toString() {
return “User{” +
“a=’” + a + ‘’’ +
“, b=’” + b + ‘’’ +
“, c=’” + c + ‘’’ +
“, d=’” + d + ‘’’ +
“, e=’” + e + ‘’’ +
‘}’;
}

}

按照如上的注解值,只有声明了 Expose 注解且 serialize 值为 true 的字段才能被序列化,只有声明了 Expose 注解且 deserialize 值为 true 的字段才能被反序列化

public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
User user = new User(“A”, “B”, “C”, “D”, “E”);
System.out.println();
System.out.println(gson.toJson(user));

String json = “{“a”:“A”,“b”:“B”,“c”:“C”,“d”:“D”,“e”:“E”}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user.toString());
}

3.2、基于版本

Gson 提供了 @Since 和 @Until 两个注解基于版本对字段进行过滤,@Since 和 @Until 都包含一个 Double 属性值,用于设置版本号。Since 的意思是“自……开始”,Until 的意思是“到……为止”,一样要和 GsonBuilder 配合使用。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Since {
double value();
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Until {
double value();
}

当版本( GsonBuilder 设置的版本) 大于或等于 Since 属性值或小于 Until 属性值时字段会进行序列化和反序列化操作,而没有声明注解的字段都会加入序列化和反序列操作

现在来看个例子,修改 User 类

/**

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

@Since(1.4)
private String a;

@Since(1.6)
private String b;

@Since(1.8)
private String c;

@Until(1.6)
private String d;

@Until(2.0)
private String e;

public User(String a, String b, String c, String d, String e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}

@Override
public String toString() {
return “User{” +
“a=’” + a + ‘’’ +
“, b=’” + b + ‘’’ +
“, c=’” + c + ‘’’ +
“, d=’” + d + ‘’’ +
“, e=’” + e + ‘’’ +
‘}’;
}

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().setVersion(1.6).create();
User user = new User(“A”, “B”, “C”, “D”, “E”);
System.out.println();
System.out.println(gson.toJson(user));

String json = “{“a”:“A”,“b”:“B”,“c”:“C”,“d”:“D”,“e”:“E”}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user.toString());
}

3.3、基于访问修饰符

访问修饰符由 java.lang.reflect.Modifier 提供 int 类型的定义,而 GsonBuilder 对象的 excludeFieldsWithModifiers方法接收一个 int 类型可变参数,指定不进行序列化和反序列化操作的访问修饰符字段 看个例子

/**

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

public String publicField = “public”;

protected String protectedField = “protected”;

private String privateField = “private”;

String defaultField = “default”;

final String finalField = “final”;

static String staticField = “static”;

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.STATIC).create();
ModifierSample modifierSample = new ModifierSample();
System.out.println(gson.toJson(modifierSample));
}

3.4、基于策略

GsonBuilder 类包含 setExclusionStrategies(ExclusionStrategy... strategies)方法用于传入不定长参数的策略方法,用于直接排除指定字段名或者指定字段类型 看个例子

/**

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

private String stringField;

private int intField;

private double doubleField;

hModifiers(Modifier.PRIVATE, Modifier.STATIC).create();
ModifierSample modifierSample = new ModifierSample();
System.out.println(gson.toJson(modifierSample));
}

[外链图片转存中…(img-U4HOWycx-1640835873719)]

3.4、基于策略

GsonBuilder 类包含 setExclusionStrategies(ExclusionStrategy... strategies)方法用于传入不定长参数的策略方法,用于直接排除指定字段名或者指定字段类型 看个例子

/**

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

private String stringField;

private int intField;

private double doubleField;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值