您的位置:首页 > Web前端 > JavaScript

Gson详细使用,此Gson非彼Json,你值得拥有~

2016-03-21 23:15 471 查看

额~先来一句官方的话

Gson是谷歌推出的解析json数据以及将对象转换成json数据的一个开源框架. 现在json因其易读性和高效率而被广泛的使用着. 相对于java以及其它json的解析框架,Gson非常的好用.

熟悉网络编程的人知道,网络请求返回的数据格式一般要么是json,要么是xml,但是采用json格式这种方式是使用的最为广泛的。

网络请求返回的json数据时,使用JSONObject或者JSONArray来承载数据,然后把返回的数据当作一个字典,根据键取出相应的值。

现在假如网络请求返回这样一个数据:

{

“city”: “北京”,

“cityId”: “10000000001”,

“temp”: “24”,

“wd”: “南风”,

“ws”: “2级”,

“sd”: “74%”,

“wse”: “2”,

“time”: “17:45”,

“isReader”: “1”,

“Radar”: “JC_RADAR_AZ9010_JB”,

“njd”: “暂无实况\t”,

“qy”: “1005”

}

那么在使用Json在解析这段数据的时候是依据每一个Key来取值的。

那我们要一次知道如下一些键值key才能取到相应的value.

city ,cityId,temp,wd,ws,sd,wse,time,isReader,Radar;

如果在做项目的时候后台给的接口不是很多,那么采用这种方式还是可以接受的,如果后台接口没有设计好,可能要改变几个接口,增添若干个字段,或删除若干个字段,那么对于前端开发人员来说这是难以接受的,而且对于整个项目来说也是非常难以接受,对于这样的后台开发者来说,我个人觉得那是要拖出来枪毙的,因为接口一改变,对于大一点的项目来说,Android,IOS,Web,微信等等前端开发,都需要进行相应的改变,需要改变重新调整数据实体和修改相应json解析,如果项目很大的话,即便修改一点点也是非常耗时间的。曾经年少无知做过这样的项目,还好和自己的好朋友同学一起开发,不过也因此发生过严重的争执,感谢自己的当时的忍耐,没有打起来。不过现在仍然是好朋友^_^.如果当时要是知道了有Gson这吊炸天的玩意儿,也许就不会发生那么多不愉快的事情了,当然现在不仅仅只有Gson,还有fastJson也有同样的功能,好吧,下面我们来看看Gson是如何的吊炸天。

在此之前,我们需要准备gson.jar

可以到官网下载:

http://mvnrepository.com/artifact/com.google.code.gson/gson



点击下载



我下载的是最新的,2.6.2版本的,链接不上的也可以直接在这里下载

好了现在开始讲解介绍gson了

1.在调用JSON操作时,gson实例不维护任何状态。所以,你可以重复使用同一对象的多个JSON序列化和反序列化操作。

(Serialization)序列化操作如下:

import com.google.gson.Gson;
public class Demo04 {
public static void main(String[] args) {
Gson gson = new Gson();
String s = gson.toJson(11111);
System.out.println("(11111)->"+s);
s = gson.toJson("abcdefg");
System.out.println("(abcd)->"+s);
s = gson.toJson(new Long(10));
System.out.println("(10)->"+s);
int[] values = { 1 ,2,3,4,5,6};
s = gson.toJson(values);
System.out.println("(1 ,2,3,4,5,6)->"+s);
}
}


控制台输出:

(11111)->11111

(abcd)->”abcdefg”

(10)->10

(1 ,2,3,4,5,6)->[1,2,3,4,5,6]

(Deserialization)反序列化操作如下:

import java.util.List;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Demo05 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
System.out.println("one:" + one);
Integer integer = gson.fromJson("1", Integer.class);
System.out.println("integer:" + integer);
Long long1 = gson.fromJson("1", Long.class);
System.out.println("long1:" + long1);
Boolean boolean1 = gson.fromJson("false", Boolean.class);
System.out.println("boolean1:" + boolean1);
String str = gson.fromJson("\"abc\"", String.class);
System.out.println("str:" + str);
List<String> list = gson.fromJson("[\"abc\",\"def\"]",
new TypeToken<List<String>>() {
}.getType());
System.out.println("list:" + list);
}

}


控制台输出:

one:1

integer:1

long1:1

boolean1:false

str:abc

list:[abc, def]

2.(对象例子)Object Examples

实体如下:

package domain;
import java.util.Date;

public class Student {
private int id;
private String name;
private Date birthDay;

public Student(){}

public Student(int id, String name, Date birthDay) {
super();
this.id = id;
this.name = name;
this.birthDay = birthDay;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Date getBirthDay() {
return birthDay;
}

public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}

public String toString() {
return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
+ name + "]";
}

}


(Serialization)序列化操作如下:

import com.google.gson.Gson;
public class Demo03 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Weather w = new Weather("北京", "10000000001", "24", "南风", "2级", "74%",
"2", "17:45", "1", "JC_RADAR_AZ9010_JB", "暂无实况  ", "1005");
Gson gson = new Gson();
System.out.println(gson.toJson(w));
}

}


控制台输出(手动转成Json格式):

{

“city”: “北京”,

“cityId”: “10000000001”,

“temp”: “24”,

“wd”: “南风”,

“ws”: “2级”,

“sd”: “74%”,

“wse”: “2”,

“time”: “17:45”,

“isReader”: “1”,

“Radar”: “JC_RADAR_AZ9010_JB”,

“njd”: “暂无实况\t”,

“qy”: “1005”

}

(Deserialization)反序列化操作如下:

import com.google.gson.Gson;
public class Demo03 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Weather w = new Weather("北京", "10000000001", "24", "南风", "2级", "74%",
"2", "17:45", "1", "JC_RADAR_AZ9010_JB", "暂无实况  ", "1005");
Gson gson = new Gson();
String json = gson.toJson(w);
System.out.println("json输出:"+json);
System.out.println("-----------------------------------------");
Weather w2 = gson.fromJson(json, Weather.class);
System.out.println("对象输出:"+w2);
}

}


控制台输出:

json输出(便于观察,转成json格式排版):
{
"city": "北京",
"cityId": "10000000001",
"temp": "24",
"wd": "南风",
"ws": "2级",
"sd": "74%",
"wse": "2",
"time": "17:45",
"isReader": "1",
"Radar": "JC_RADAR_AZ9010_JB",
"njd": "暂无实况\t",
"qy": "1005"
}
-----------------------------------------
对象输出(便于观察,转成json格式排版,实际toString):
Weather[
city=北京,
cityId=10000000001,
temp=24,
wd=南风,
ws=2级,
sd=74%,
wse=2,
time=17: 45,
isReader=1,
Radar=JC_RADAR_AZ9010_JB,
njd=暂无实况,
qy=1005
]


3.现在来个稍微复杂一点的包含内部类

实体如下(BoyStudent 包含Student内部类):

public class Student {
private int id;
private String name;
private Date birthDay;
public Student(){}
public Student(int id, String name, Date birthDay) {
super();
this.id = id;
this.name = name;
this.birthDay = birthDay;
}
public String toString() {
return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
+ name + "]";
}
}

public class BoyStudent {
private String sex;
private String intertests;
private Student student;
@Override
public String toString() {
return "Boy [sex=" + sex + ", intertests=" + intertests + ", student="
+ student + "]";
}
public Boy(String sex, String intertests, Student student) {
super();
this.sex = sex;
this.intertests = intertests;
this.student = student;
}
public Boy() {
}
}


(Serialization)序列化,(Deserialization)反序列化操作操作如下:

public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new Gson();
Student s1 = new Student(1,"s1",new Date());
BoyStudent b1 = new BoyStudent("m", "篮球", s1);
String json1 = gson.toJson(b1);
System.out.println("json1:"+json1);
System.out.println("---------------------------");
BoyStudent bTemp = gson.fromJson(json1, BoyStudent.class);
System.out.println("bTemp:"+bTemp);
}


输出:

json1:
{
"sex": "m",
"intertests": "篮球",
"student": {
"id": 1,
"name": "s1",
"birthDay": "Mar 21, 2016 9:44:05 PM"
}
}
---------------------------
bTemp:
BoyStudent[
sex=m,
intertests=篮球,
student=Student[
birthDay=MonMar2121: 44: 05CST2016,
id=1,
name=s1
]
]


4.在开发中那么这还是仅仅不够的,进场返回来的json数据是一个集合,那么gson能否实现呢?哈哈~那是必须的,现在来个复杂一点的。

实体如下:

public class ResponseBoyStudent {
private int errCode;
private String note;
private BoyStudent boyStudent;
public ResponseBoyStudent(int errCode, String note, BoyStudent boyStudent) {
super();
this.errCode = errCode;
this.note = note;
this.boyStudent = boyStudent;
}
@Override
public String toString() {
return "ResponseBoyStudent [errCode=" + errCode + ", note=" + note
+ ", boyStudent=" + boyStudent + "]";
}
}


(Serialization)序列化,(Deserialization)反序列化操作操作如下:

public static void main(String[] args) {
// TODO Auto-generated method stub
Student s1 = new Student(1, "TFboys-1", new Date());
Student s2 = new Student(2, "TFboys-2", new Date());
Student s3 = new Student(3, "TFboys-3", new Date());

BoyStudent b1 = new BoyStudent("M", "唱歌", s1);
BoyStudent b2 = new BoyStudent("M", "跳舞", s2);
BoyStudent b3 = new BoyStudent("M", "啥都不会", s3);

ResponseBoyStudent rbs1 = new ResponseBoyStudent(200, "Ok", b1);
ResponseBoyStudent rbs2 = new ResponseBoyStudent(302, "跳转", b2);
ResponseBoyStudent rbs3 = new ResponseBoyStudent(404, "资源请求失败", null);

List<ResponseBoyStudent> tfboys = new ArrayList<ResponseBoyStudent>();
tfboys.add(rbs1);
tfboys.add(rbs2);
tfboys.add(rbs3);

Gson gson = new Gson();
String json = gson.toJson(tfboys);
System.out.println(json);

System.out.println("--------------------------------");

List<ResponseBoyStudent> rec_tfboys = gson.fromJson(json,
new TypeToken<List<ResponseBoyStudent>>() {
}.getType());
System.out.println(rec_tfboys);

}


控制台输出:

[
{
"errCode": 200,
"note": "Ok",
"boyStudent": {
"sex": "M",
"intertests": "唱歌",
"student": {
"id": 1,
"name": "TFboys-1",
"birthDay": "Mar 21, 2016 10:06:54 PM"
}
}
},
{
"errCode": 302,
"note": "跳转",
"boyStudent": {
"sex": "M",
"intertests": "跳舞",
"student": {
"id": 2,
"name": "TFboys-2",
"birthDay": "Mar 21, 2016 10:06:54 PM"
}
}
},
{
"errCode": 404,
"note": "资源请求失败"
}
]
--------------------------------
[
ResponseBoyStudent[
errCode=200,
note=Ok,
boyStudent=BoyStudent[
sex=M,
intertests=唱歌,
student=Student[
birthDay=MonMar2122: 06: 54CST2016,
id=1,
name=TFboys-1
]
]
],
ResponseBoyStudent[
errCode=302,
note=跳转,
boyStudent=BoyStudent[
sex=M,
intertests=跳舞,
student=Student[
birthDay=MonMar2122: 06: 54CST2016,
id=2,
name=TFboys-2
]
]
],
ResponseBoyStudent[
errCode=404,
note=资源请求失败,
boyStudent=null
]
]


看到这里有木有想哭的赶脚,之前写的代码真叫尼玛一个累~

注意:好好观察哦,当404传入为空的时候,在生成Json字符串是没有boyStudent这个键值的,同时当反序列化为list对象时boyStudent是为空的!

好了看到这里,会想到另外一种需求,BoyStudent不能为空,而且它是有默认值的,但是返回来的却是null,那么在程序中像这样rec_tfboys.get(postion).getBoyStudent().get….使用是一定会报空指针异常的。总不至于不让后台传入空值吧?会不会有其他的解决办法呢?带着问题思考,既然提到这里了,答案一定是有的,再次之前就说Gson吊炸天了吧!我说的没错吧,废话不多说,直接来码代码吧~^_^

我对几个实体类稍微做了一下修改,注意观察修改了那些内容,注意哪些是变化的,哪些是没有变化的

public class Student {
private int id;
private String name;
private Date birthDay;
/////////////////////Change/////////////////////////////
public Student(){
this.id = 0;
this.name = "请输入您的姓名";
this.birthDay = new Date();
}
/////////////////////Change/////////////////////////////

public Student(int id, String name, Date birthDay) {
super();
this.id = id;
this.name = name;
this.birthDay = birthDay;
}
public String toString() {
return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
+ name + "]";
}
}

public class BoyStudent {
private String sex;
private String intertests;
private Student student;
@Override
public String toString() {
return "BoyStudent [sex=" + sex + ", intertests=" + intertests + ", student="
+ student + "]";
}

public BoyStudent(String sex, String intertests, Student student) {
super();
this.sex = sex;
this.intertests = intertests;
this.student = student;
}
/////////////////////Change/////////////////////////////
public BoyStudent() {
this.sex = "M";
this.intertests = "左手右手一个慢动作";
this.student = new Student(1000, "请输入您的姓名", new Date());
}
/////////////////////Change/////////////////////////////
}

public class ResponseBoyStudent {
private int errCode;
private String note;
private BoyStudent boyStudent;
public ResponseBoyStudent(int errCode, String note, BoyStudent boyStudent) {
super();
this.errCode = errCode;
this.note = note;
this.boyStudent = boyStudent;
}
/////////////////////Change/////////////////////////////
public ResponseBoyStudent(){
boyStudent = new BoyStudent("M","睡觉",new Student());
}
//////////////////////////////////////////////////
@Override
public String toString() {
return "ResponseBoyStudent [errCode=" + errCode + ", note=" + note
+ ", boyStudent=" + boyStudent + "]";
}
}


我将用斜线表示出来改变的部分,一次是对其无参构造函数进行了修改,我们来看看效果是否如我们所想那样。

序列化反序列化操作操作代码未进行修改。

控制台输出:

[
{
"errCode": 200,
"note": "Ok",
"boyStudent": {
"sex": "M",
"intertests": "唱歌",
"student": {
"id": 1,
"name": "TFboys-1",
"birthDay": "Mar 21, 2016 10:41:43 PM"
}
}
},
{
"errCode": 302,
"note": "跳转",
"boyStudent": {
"sex": "M",
"intertests": "跳舞",
"student": {
"id": 2,
"name": "TFboys-2",
"birthDay": "Mar 21, 2016 10:41:43 PM"
}
}
},
{
"errCode": 404,
"note": "资源请求失败"
}
]
--------------------------------
[
ResponseBoyStudent[
errCode=200,
note=Ok,
boyStudent=BoyStudent[
sex=M,
intertests=唱歌,
student=Student[
birthDay=MonMar2122: 41: 43CST2016,
id=1,
name=TFboys-1
]
]
],
ResponseBoyStudent[
errCode=302,
note=跳转,
boyStudent=BoyStudent[
sex=M,
intertests=跳舞,
student=Student[
birthDay=MonMar2122: 41: 43CST2016,
id=2,
name=TFboys-2
]
]
],
ResponseBoyStudent[
errCode=404,
note=资源请求失败,
boyStudent=BoyStudent[
sex=M,
intertests=睡觉,
student=Student[
birthDay=MonMar2122: 41: 43CST2016,
id=0,
name=请输入您的姓名
]
]
]
]


**可以发现json字符串未发生改变,但是反序列化的list的内容都是部位空的,可以推出,json字符串中缺少键值的时候仍会去“调用”默认构造函数。

5.既然能让空的json反序列话为不为null的实例,那能不能返回null?不买关子了,是有的^_^.

代码很简单:

public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(null);
System.out.println(json);
}


控制台输出:

null


为什么非要去Builder一个Gson实例呢,难道直接new 出来的不可以吗?亲测确实可以,但是这两种方式有什么区别呢?

public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new Gson();
String json = gson.toJson(null);
System.out.println(json);
}


控制台输出:

null


好,那我么就来观察它的区别吧!

直接上代码了

实体如下:

public class Foo {
private final String s;
private final int i;
public Foo() {
this(null, 5);
}
public Foo(String s, int i) {
this.s = s;
this.i = i;
}
@Override
public String toString() {
return "Foo [s=" + s + ", i=" + i + "]";
}
}


(Serialization)序列化,(Deserialization)反序列化操作操作如下:

先看直接new出来的Gson

public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new Gson();
Foo foo = new Foo();
String json = gson.toJson(foo);
System.out.println(json);
Foo f = gson.fromJson(json, Foo.class);
System.out.println("f:"+f);
json = gson.toJson(null);
System.out.println(json);
}


控制台输出:

{"i":5}
f:Foo [s=null, i=5]
null


在biu~出来的效果

public static void main(String[] args) {
// TODO Auto-generated method stub
Gson gson = new GsonBuilder().serializeNulls().create();
Foo foo = new Foo();
String json = gson.toJson(foo);
System.out.println(json);
Foo f = gson.fromJson(json, Foo.class);
System.out.println("f:"+f);
json = gson.toJson(null);
System.out.println(json);
}


控制台输出:

{"s":null,"i":5}
f:Foo [s=null, i=5]
null


看出二者的区别了吧,当使用biu~方式时属性为空的时候输出来的json字符串是有键值key的,而直接new出来的就没有。

非常感谢看到这里的朋友,最后送点一个非常实用的工具给你

这个工具叫做json实体转换器,用法很简单,我直接贴图就好了。



确认提交之后将自动生成相应的实体



看看生成的实体张什么样子吧

工具下载地址:http://download.csdn.net/detail/u013922681/9468715

package domain;

import java.lang.reflect.Field;
import java.io.Serializable;
import java.util.List;

public class JavaName implements Serializable {
public String note;
public int errCode;
public BoyStudent boyStudent;

public class BoyStudent implements Serializable {
public String sex;
public String intertests;
public Student student;

public class Student implements Serializable {
public String birthDay;
public String name;
public int id;

public void setBirthDay(String birthDay) {
this.birthDay = birthDay;
}

public String getBirthDay() {
return this.birthDay;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

public void setId(int id) {
this.id = id;
}

public int getId() {
return this.id;
}

public String toString() {
String s = "";
Field[] arr = this.getClass().getFields();
for (Field f : getClass().getFields()) {
try {
s += f.getName() + "=" + f.get(this) + "\n,";
} catch (Exception e) {
}
}
return getClass().getSimpleName()
+ "["
+ (arr.length == 0 ? s : s.substring(0, s.length() - 1))
+ "]";
}
}

public void setSex(String sex) {
this.sex = sex;
}

public String getSex() {
return this.sex;
}

public void setIntertests(String intertests) {
this.intertests = intertests;
}

public String getIntertests() {
return this.intertests;
}

public String toString() {
String s = "";
Field[] arr = this.getClass().getFields();
for (Field f : getClass().getFields()) {
try {
s += f.getName() + "=" + f.get(this) + "\n,";
} catch (Exception e) {
}
}
return getClass().getSimpleName() + "["
+ (arr.length == 0 ? s : s.substring(0, s.length() - 1))
+ "]";
}
}

public void setNote(String note) {
this.note = note;
}

public String getNote() {
return this.note;
}

public void setErrCode(int errCode) {
this.errCode = errCode;
}

public int getErrCode() {
return this.errCode;
}

public String toString() {
String s = "";
Field[] arr = this.getClass().getFields();
for (Field f : getClass().getFields()) {
try {
s += f.getName() + "=" + f.get(this) + "\n,";
} catch (Exception e) {
}
}
return getClass().getSimpleName() + "["
+ (arr.length == 0 ? s : s.substring(0, s.length() - 1)) + "]";
}
}


好了,第一次写这么认真~觉得可以的话点个赞!

对了,能看官网的demo就看官网的吧!

链接如下:https://sites.google.com/site/gson/gson-user-guide#TOC-Gson-Users
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gson