1.实现原理
基于事件驱动
2.JsonElement
抽象类,代表json中的某一个元素(jsonObject/jsonArray/null/基本类型)
3.Json解析流程
4.Gson反射解析流程
5.解析流程
- 根据所需要的数据建立一个对应json数据的java bean类 ,即可通过简单的操作解析出需要的数据
6.Gson的使用
通过new Gson() 来创建对象
static class GsonBean{
public int age;
public String name;
}
public static void main(String[] args) {
//创建gson对象
Gson gson=new Gson();
//将数据转换为json字符串
System.out.println(gson.toJson(1));
System.out.println(gson.toJson("zeo"));
int[] values={1,2,3};
System.out.println( gson.toJson(values));
int i=gson.fromJson("1",Integer.class);
System.out.println("i:"+i);
//将java bean 转换为json字符串
GsonBean bean=new GsonBean();
bean.name="java";
bean.age=20;
String json= gson.toJson(bean);
System.out.println(json);
//将 json字符串转换为java bean
GsonBean bean1=gson.fromJson(json,GsonBean.class);
System.out.println("bean1:"+bean1);
}
//打印信息 我们可以看到gson可以将任意类型的数据转换为json字符串
1
"zeo"
[1,2,3]
i:1
{"age":20,"name":"java"}
bean1:com.example.gson.GsonExample$GsonBean@14514713
说明
- 1.Gson可以将任意的数据转换为json字符串
- 2.toJson()用于将Java Object转换为json字符串
- 3.fromJson()用于将json字符串转换为Java Object
通过构建者模式创建对象
static class Foo{
private String s;
private int i;
public Foo() {
this(null,5);
}
public Foo(String s, int i) {
this.s = s;
this.i = i;
}
}
public static void main(String[] args) {
System.out.println("传统解析方式如下");
Gson gson = new GsonBuilder()
.setPrettyPrinting()//设置以json的格式输出字符串,默认就是输出一个json字符串
.serializeNulls()//对空字段的数据进行序列化 默认对空数据字段是省略的
.create();
Foo foo=new Foo();
String json= gson.toJson(foo);
System.out.println(json);
System.out.println("自定义解析器如下");
Gson gson2 = new GsonBuilder().registerTypeAdapter(Foo.class, new TypeAdapter<Foo>() {
@Override
public void write(JsonWriter out, Foo value) throws IOException {
out.beginObject();
out.name("s").value(value.s);
out.name("i").value(value.i+1);
out.endObject();
}
@Override
public Foo read(JsonReader in) throws IOException {
Foo foo1=new Foo();
in.beginObject();
while (in.hasNext()){
switch (in.nextName()){
case "s":
foo1.s=in.nextString();
break;
case "i":
foo1.i=in.nextInt();
break;
}
}
in.endObject();;
return foo1;
}
}.nullSafe()).setPrettyPrinting().serializeNulls().create();
Foo foo1=new Foo();
String json1= gson2.toJson(foo1);
System.out.println(json1);
}
//打印日志
传统解析方式如下
{
"s": null,
"i": 5
}
自定义解析器如下
{
"s": null,
"i": 6
}
说明
- 1.通过GsonBuilder().create()创建gson对象
- 2.setPrettyPrinting() 调用该方法后,打印json字符串将使用一种漂亮的方式,默认就是一行json字符串
- 3.serializeNulls() 默认gson不对空数据字段进行序列化,设置该方法后,对空数据字段也会进行序列化
- 4.registerTypeAdapter 自定义一个解析器,可以对数据进行写入和读取,并在这个过程中可以进行一些额外的操作
- 5.nullSafe() 调用该方法之后gson会对字段数据进行空检查,外部无序进行空检查
- 6.JsonWriter/JsonReader就是输出/输入流,用于写入和读取数据
Gson注解使用之SerializeName
static class SerializedNameBean {
@SerializedName("name")
public String a;
@SerializedName(value = "name1")
public String b;
public String c;
public SerializedNameBean(String a, String b, String c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public String toString() {
return "SerializedNameBean{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
public static void main(String[] args) {
System.out.println("gson注解之SerializedName");
SerializedNameBean data=new SerializedNameBean("v1","v2","v3");
Gson gson=new GsonBuilder()
.setPrettyPrinting()
.create();
String json= gson.toJson(data);
System.out.println(json);
SerializedNameBean data1=gson.fromJson(json,SerializedNameBean.class);
System.out.println(data1.a);
System.out.println(data1.b);
System.out.println(data1.c);
System.out.println(data1.toString());
}
//打印信息
{
"name": "v1",
"name1": "v2",
"c": "v3"
}
v1
v2
v3
SerializedNameBean{a='v1', b='v2', c='v3'}
说明
- SerializedName:用于将json字符串中的字段和java对象中的字段相匹配,也就是说即使java 中的字段和json中的字段名不相同也可以 可以通过注解进行匹配
Gson注解使用之Until
static class UntilBean{
//一直参与序列化和反序列化
private String firstName;
//一直参与序列化和反序列化
private String lastName;
//版本<=1.1时 参与序列化和反序列化
@Until(1.1) private String emailAddress;
//版本<=1.1时 参与序列化和反序列化
@Until(1.1) private String password;
@Override
public String toString() {
return "UntilBean{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", emailAddress='" + emailAddress + '\'' +
", password='" + password + '\'' +
'}';
}
}
public static void main(String[] args) {
//Util注解
System.out.println("Util注解 <=");
UntilBean untilBean=new UntilBean();
untilBean.firstName="jing";
untilBean.lastName="java";
untilBean.emailAddress="123@qq.com";
untilBean.password="123";
System.out.println("until 原数据:"+untilBean.toString());
Gson untilGson=new GsonBuilder().setVersion(1.2).create();
String untilJson=untilGson.toJson(untilBean);
System.out.println("until version 1.2 java bean 转 json:"+untilJson);
UntilBean untilBean1 = untilGson.fromJson(untilJson, UntilBean.class);
System.out.println("until version 1.2 json 转 java bean:"+untilBean1.toString());
}
//打印信息
//当我们设置version为1.2的时候的打印信息
until 原数据:UntilBean{firstName='jing', lastName='java', emailAddress='123@qq.com', password='123'}
until version 1.2 java bean 转 json:{"firstName":"jing","lastName":"java"}
until version 1.2 json 转 java bean:UntilBean{firstName='jing', lastName='java', emailAddress='null', password='null'}
//当我们设置version为1.1的时候的打印信息
until 原数据:UntilBean{firstName='jing', lastName='java', emailAddress='123@qq.com', password='123'}
until version 1.2 java bean 转 json:{"firstName":"jing","lastName":"java"}
until version 1.2 json 转 java bean:UntilBean{firstName='jing', lastName='java', emailAddress='null', password='null'}
说明
- 1.Until:标识属性在什么版本下可以参与序列化和反序列化,
- 2.我们可以看到 当在属性上面标记Until注解中设置为1.1,即表示在版本小于等于1.1条件下都可以参与序列化和反序列,若设置版本大于1.1,则属性不参与序列化和反序列化
- 3.若属性不设置注解,默认参与序列化和反序列
Gson注解使用之Since
static class SinceBean{
//一直参与序列化和反序列化
private String firstName;
//一直参与序列化和反序列化
private String lastName;
//版本>=1.1时 参与序列化和反序列化
@Since(1.1) private String emailAddress;
//版本>=1.1时 参与序列化和反序列化
@Since(1.1) private String password;
@Override
public String toString() {
return "SinceBean{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", emailAddress='" + emailAddress + '\'' +
", password='" + password + '\'' +
'}';
}
}
public static void main(String[] args) {
//Since注解
System.out.println("Since注解 >=");
SinceBean sinceBean=new SinceBean();
sinceBean.firstName="jing";
sinceBean.lastName="java";
sinceBean.emailAddress="123@qq.com";
sinceBean.password="123";
System.out.println("Since 原数据:"+sinceBean.toString());
Gson untilGson=new GsonBuilder().setVersion(1.0).create();
String untilJson=untilGson.toJson(sinceBean);
System.out.println("Since version 1.5 java bean 转 json:"+untilJson);
SinceBean sinceBean1 = untilGson.fromJson(untilJson, SinceBean.class);
System.out.println("Since version 1.5 json 转 java bean:"+sinceBean1.toString());
}
//打印信息
//当版本大于等于1.1 为1.5的时候
Since 原数据:SinceBean{firstName='jing', lastName='java', emailAddress='123@qq.com', password='123'}
Since version 1.5 java bean 转 json:{"firstName":"jing","lastName":"java"}
Since version 1.5 json 转 java bean:SinceBean{firstName='jing', lastName='java', emailAddress='null', password='null'}
//当版本小于1.1 为1.0的时候
Since 原数据:SinceBean{firstName='jing', lastName='java', emailAddress='123@qq.com', password='123'}
Since version 1.0 java bean 转 json:{"firstName":"jing","lastName":"java"}
Since version 1.0 json 转 java bean:SinceBean{firstName='jing', lastName='java', emailAddress='null', password='null'}
说明
- 1.Since:标识属性在什么版本下可以参与序列化和反序列化,
- 2.我们可以看到 当在属性上面标记Since注解中设置为1.1,即表示在版本大于等于1.1条件下都可以参与序列化和反序列,若设置版本小于1.1,则属性不参与序列化和反序列化
- 3.若属性不设置注解,默认参与序列化和反序列
Gson注解之JsonAdapter
//通过注解设置一个解析器
@JsonAdapter(CustomJsonAdapter.class)
static class JsonAdapterBean {
//一直参与序列化和反序列化
private String firstName;
//一直参与序列化和反序列化
private String lastName;
public JsonAdapterBean(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return "JsonAdapterBean{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
static class CustomJsonAdapter extends TypeAdapter<JsonAdapterBean> {
@Override
public void write(JsonWriter out, JsonAdapterBean value) throws IOException {
//写入json数据 name为"name" value为value.firstName + " " + value.lastName
//最终的json字符串为{"name":"java php"}
out.beginObject();
out.name("name");
out.value(value.firstName + " " + value.lastName);
out.endObject();
}
@Override
public JsonAdapterBean read(JsonReader in) throws IOException {
//读取数据 指针指向有效数据 然后获取对应的value 将其进行拆分
//最总将数组的值进行赋值 JsonAdapterBean{firstName='java', lastName='php'}
in.beginObject();
in.nextName();
String[] nameParts = in.nextString().split(" ");
in.endObject();
return new JsonAdapterBean(nameParts[0], nameParts[1]);
}
}
public static void main(String[] args) {
//JsonAdapter
JsonAdapterBean jsonAdapterBean = new JsonAdapterBean("java", "php");
System.out.println("JsonAdapter 原数据:" + jsonAdapterBean.toString());
Gson jsonAdapterGson = new GsonBuilder().setVersion(1.0).create();
String untilJson = jsonAdapterGson.toJson(jsonAdapterBean);
System.out.println("JsonAdapter 自定义解析器 java bean 转 json:" + untilJson);
JsonAdapterBean jsonAdapterBean1 = jsonAdapterGson.fromJson(untilJson, JsonAdapterBean.class);
System.out.println("JsonAdapter 自定义解析器 json 转 java bean:" + jsonAdapterBean1.toString());
}
//打印信息
JsonAdapter 原数据:JsonAdapterBean{firstName='java', lastName='php'}
JsonAdapter 自定义解析器 java bean 转 json:{"name":"java php"}
JsonAdapter 自定义解析器 json 转 java bean:JsonAdapterBean{firstName='java', lastName='php'}
说明
-
JsonAdapter: 给java bean设置一个自定义解析器
-
在CustomJsonAdapter中我们继承TypeAdapter类,并重写了write和read方法
-
在write中写入json数据 name为"name" value为value.firstName + " " + value.lastName,最总的json字符串为:{“name”:“java php”}
-
在read中读取json数据。首先指针指向有效数据 获取对应的value 将其进行拆分,最后将数组的值赋值到java bean中,最终java bean为:JsonAdapterBean{firstName=‘java’, lastName=‘php’}
Gson注解之Expose
static class ExposeBean {
//参与序列化和反序列化
@Expose
private String firstName;
//参与序列化 但不参与反序列化
@Expose(serialize = true, deserialize = true)
private String lastName;
//不参与序列化和反序列化
@Expose(serialize = false, deserialize = true)
private String emailAddress;
//不参与序列化和反序列化
private String password;
public ExposeBean(String firstName, String lastName, String emailAddress, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.emailAddress = emailAddress;
this.password = password;
}
@Override
public String toString() {
return "ExposeBean{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", emailAddress='" + emailAddress + '\'' +
", password='" + password + '\'' +
'}';
}
}
public static void main(String[] args) {
System.out.println("gson注解之Expose");
Gson gson1=new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create();
ExposeBean mExposeBean=new ExposeBean("jing","mei","779889045@qq.com","1333");
String json1=gson1.toJson(mExposeBean);
System.out.println(json1);
ExposeBean data2=gson1.fromJson(json1,ExposeBean.class);
System.out.println(data2.firstName);
System.out.println(data2.lastName);
System.out.println(data2.emailAddress);
System.out.println(data2.password);
System.out.println(data2.toString());
}
//打印信息
gson注解之Expose
{
"firstName": "jing",
"lastName": "mei"
}
jing
mei
null
null
ExposeBean{firstName='jing', lastName='mei', emailAddress='null', password='null'}
说明
- 1.Expose:标识属性是否可以被序列化和反序列化
- 2.Expose里面有两个属性可以配置:serialize表示是否可以序列化(true可以 false不可以); deserialize表示是否可以反序列化(true可以,false不可以)
- 3.Expose注解的使用必须要excludeFieldsWithoutExposeAnnotation()的配合,否则无效,所以需要通过GsonBuilder来构建Gson对象
- 4.从打印信息我们可以看出若java bean转换为json过程中属性不能序列化,那么反序列化也是空的;若需要反序列化有效,必须是序列化有效的
Gson之自定义反序列
public class GsonDeserializer {
private String name;
private List<AuthorsBean> authors;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<AuthorsBean> getAuthors() {
return authors;
}
public void setAuthors(List<AuthorsBean> authors) {
this.authors = authors;
}
@Override
public String toString() {
return "GsonDeserializer{" +
"name='" + name + '\'' +
", authors=" + authors +
'}';
}
static class AuthorsBean{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "AuthorsBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
String json = "{\n" +
" \"name\": \"java\",\n" +
" \"authors\": \"\"\n" +
"}";
Gson gson = new Gson();
GsonDeserializer gsonError1 = gson.fromJson(json, GsonDeserializer.class);
System.out.println(gsonError1);
}
//打印信息
GsonDeserializer{name='java', authors=[AuthorsBean{id='1'', name='Joshua Bloch''}, AuthorsBean{id='2'', name='Tom'}]}
说明
从例子中我们可以看到 json字符串的格式和java bean的格式相对应的时候,反序列化是正常的
public class GsonDeserializer {
private String name;
private List<AuthorsBean> authors;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<AuthorsBean> getAuthors() {
return authors;
}
public void setAuthors(List<AuthorsBean> authors) {
this.authors = authors;
}
@Override
public String toString() {
return "GsonDeserializer{" +
"name='" + name + '\'' +
", authors=" + authors +
'}';
}
static class AuthorsBean{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "AuthorsBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
String json = "{\n" +
" \"name\": \"java\",\n" +
" \"authors\": \"\"\n" +
"}";
Gson gson = new Gson();
GsonDeserializer gsonError1 = gson.fromJson(json, GsonDeserializer.class);
System.out.println(gsonError1);
}
//打印信息
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 3 column 17 path $.authors
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
说明
从实例中我们看到json字符串中author字段为空,但是java bean中author字段时集合,所以在反序列化过程中会报错
public class GsonDeserializer {
private String name;
private List<AuthorsBean> authors;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<AuthorsBean> getAuthors() {
return authors;
}
public void setAuthors(List<AuthorsBean> authors) {
this.authors = authors;
}
@Override
public String toString() {
return "GsonDeserializer{" +
"name='" + name + '\'' +
", authors=" + authors +
'}';
}
static class AuthorsBean{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "AuthorsBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
/**
* 自定义json反序列化
*/
static class CustomDeserializer implements JsonDeserializer<GsonDeserializer>{
@Override
public GsonDeserializer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//获取JsonObject
JsonObject jsonObject = json.getAsJsonObject();
//通过jsonObject获取name元素
JsonElement jsonTitle = jsonObject.get("name");
//获取name元素的值
String name=jsonTitle.getAsString();
//通过jsonObject获取authors元素
JsonElement jsonAuthors=jsonObject.get("authors");
GsonDeserializer gsonDeserializer=new GsonDeserializer();
//authors的值是否是数组
if(jsonAuthors.isJsonArray()){//若authors是数组类型 是我们需要的
GsonDeserializer.AuthorsBean[] authors= context.deserialize(jsonAuthors,GsonDeserializer.AuthorsBean[].class);
gsonDeserializer.setAuthors(Arrays.asList(authors));
}else{
gsonDeserializer.setAuthors(null);
}
gsonDeserializer.setName(name);
return gsonDeserializer;
}
}
static class AuthorDeserializer implements JsonDeserializer{
@Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
GsonDeserializer.AuthorsBean authorsBean=new GsonDeserializer.AuthorsBean();
authorsBean.setId(jsonObject.get("id").getAsString());
authorsBean.setName(jsonObject.get("name").getAsString());
return authorsBean;
}
}
public static void main(String[] args) {
String json = "{\n" +
" \"name\": \"java\",\n" +
" \"authors\": \"\"\n" +
"}";
Gson gson = new GsonBuilder().registerTypeAdapter(GsonDeserializer.class, new GsonDeserializer.CustomDeserializer())
.registerTypeAdapter(GsonDeserializer.AuthorsBean.class, new AuthorDeserializer())
.setPrettyPrinting()
.create();
GsonDeserializer mGsonDeserializer = gson.fromJson(json, GsonDeserializer.class);
System.out.println(mGsonDeserializer);
}
//打印信息
GsonDeserializer{name='java', authors=null}
说明
- 1.从实例中我们看到 json字符串的author字段时空,但是java bean中author时list集合,按照正常模式的话时会报错的,但是我们通过registerTypeAdapter 设置自定义反序列化器,从而避免的报错。
- 2.registerTypeAdapter()需要两个参数,第一个参数时反序列化的类型,第二参数是反序列化对象
- 3.反序列化类需要实现JsonDeserializer接口,重写deserialize方法