介绍
JSON
JSON(JavaScript Object Notation)
:轻量级的数据交换格式,广泛用于服务器和客户端的交互中
Gson
Google
公司发布的一个开放源代码的 Java
库,主要用途为序列化 Java
对象为 JSON
字符串,或反序列化 JSON
字符串成 Java
对象。官方仓库。主要优势有:
- 允许已经存在的无法改变的对象转换成 Json,或者
Json
转换成已存在的对象,不需要注解就可以直接转换 - 对泛型提供完全的支持
依赖
app/build.gradle
中增加依赖:
1 | compile 'com.google.code.gson:gson:2.8.1` |
基本概念
Gson
源码文档写的比较好,可以直接参考 JavaDoc
来看示例
部分特点
- 推荐把成员变量都声明为
private
Java
对象一定要有一个无参构造方法,这是Gson
实例化对象的关键,可以没有setter/getter
方法- 默认不需要注解字段,所有包含在当前类的字段都默认会被序列化或者反序列化
JavaBean
的生成
规则
尽量不使用内部类或嵌套类,如果使用需要使用 static 声明?
实际使用中内部类和嵌套类都能解析!使用工具将
Json
生成对应的JavaBean
先将Json
格式化,使用 bejson 生成JavaBean
序列化/反序列化
Serialization
序列化,使Java
对象到Json
字符串的过程Deserialization
反序列化,Json
字符串转换成Java
对象的过程
Gson
默认会序列化和反序列化所有属性字段,但是也可以自定义,不过现在推荐使用 TypeAdapter
。如下为自定义的方法:
- 自定义序列化的一种方法
1 | public class Id<T> { |
- 自定义反序列化的一种方法
1 | public class Id<T> { |
JsonReader/JsonWriter
JsonReader
继承于 Reader
用来读取字符,JsonWriter
继承于 Writer
用来写入字符。
JsonReader
用于将JSON
字符串转为Java
对象JsonWriter
用于将Java
对象写为JSON
字符串
TypeAdapter
TypeAdapter
是一个抽象类,可以用来自定义类型转换,它的流式 API
比树式 API
解析更高效
1 | public class PointAdapter extends TypeAdapter<Point> { |
注解关键字
包含五个注解关键字,代码路径: com.google.gson.annotations
@Expose
@Expose
注解只有在如下构造方法初始化时才生效:Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
生效时被注解的成员变量才会参与序列化/反序列化,其他不会参与。如果不是使用该构造方法,没有任何功能。
1 | public class User { |
@SerializedName
表示某个成员变量序列化/反序列化的名字。如果后台服务器使用的命名规则和 Java
规范不一致,或者返回的 Json
和 Java
类只有部分变量不一致时,通过 @SerializedName
注解转换一一对应关系
1 | public class MyClass { |
@Since
只有在如下构造方法初始化时才生效:Gson gson = new GsonBuilder().setVersion(1.0).create()
注解生效表示成员变量从哪个版本开始有效
1 | public class User { |
@Until
和 since
一样,只有在如下构造方法初始化时才生效:Gson gson = new GsonBuilder().setVersion(1.2).create()
注解生效时表示成员变量从哪个版本开始无效
1 | public class User { |
@JsonAdapter
表示成员变量或者类上使用指定的 TypeAdapter
来进行序列化/反序列化
1 | (UserJsonAdapter.class) |
特殊关键字 transient
如果被关键字 transient
申明了的字段,不会参与 Gson
的序列化和反序列化:transient int val;
使用流程
常见问题
Gson
转换过程中的空字段
如果元素看起来是个 list
,但是实际一直为空,可以直接注释掉这个字段,也就是javabean
中不需要定义 comments
字段。否则会因空报错:com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 10796 path $.data.data[3].comments[0]
包含相同字段解决方案
比如数据格式如下:
1 | "message": "success", |
这里面有两个 data
,json
转换为 javabean
时会出现重复字段,设计 javabean
可以通过将重复的类更换类名,但字段名不变:
1 | // json中的第一个 data,类名更换 |