在上一篇文章中,我们已经接触了针对JSON处理的Java API,你很容易就会发现,它并不容易使用,无论你是否必须将JSON转换为Java对象,或者其他需求,你都需要写上很多与目标JSON结构高度耦合的代码。
这也是为什么我开始留意其他能做到自行转换格式的API,Gson映入了我的眼帘。Gson是开源的,并已被广泛应用于JSON和Java中,Gson使用Java反射API,提供了诸多易于使用的方式将JSON转换为Java,反之亦然。
你可以从google的代码站点下载到Gson的jar文件,或者如果你正在使用maven,那么你所需要做的所有事情仅仅是添加以下依赖。
1
2
3
4
5
6
7
8
|
<
dependencies
>
<
dependency
>
<
groupId
>com.google.code.gson
groupId
>
<
artifactId
>gson
artifactId
>
<
version
>2.2.4
version
>
dependency
>
dependencies
>
|
Gson是非常强大的API,它支持Java泛型,支持现成的JSON与Java对象的转换,只要对象的成员名称与JSON中的一致即可。如果针对Java bean和JSON要使用不同的名称,那么可以使用@SerializedName注解来映射JSON和Java类中的变量。
我们来看一个复杂示例,在JSON中含有嵌套对象以及数组,我们要将其映射到Java bean的属性(List、Map、Array类型等)中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
{
"empID"
: 100,
"name"
:
"David"
,
"permanent"
:
false
,
"address"
: {
"street"
:
"BTM 1st Stage"
,
"city"
:
"Bangalore"
,
"zipcode"
: 560100
},
"phoneNumbers"
: [
123456,
987654
],
"role"
:
"Manager"
,
"cities"
: [
"Los Angeles"
,
"New York"
],
"properties"
: {
"age"
:
"28 years"
,
"salary"
:
"1000 Rs"
}
}
|
建立Java bean类,将JSON转换为Java对象。
Employee.java
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package
com.journaldev.json.model;
import
java.util.Arrays;
import
java.util.List;
import
java.util.Map;
import
com.google.gson.annotations.SerializedName;
public
class
Employee {
@SerializedName
(
"empID"
)
private
int
id;
private
String name;
private
boolean
permanent;
private
Address address;
private
long
[] phoneNumbers;
private
String role;
private
List
private
Map
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
boolean
isPermanent() {
return
permanent;
}
public
void
setPermanent(
boolean
permanent) {
this
.permanent = permanent;
}
public
Address getAddress() {
return
address;
}
public
void
setAddress(Address address) {
this
.address = address;
}
public
long
[] getPhoneNumbers() {
return
phoneNumbers;
}
public
void
setPhoneNumbers(
long
[] phoneNumbers) {
this
.phoneNumbers = phoneNumbers;
}
public
String getRole() {
return
role;
}
public
void
setRole(String role) {
this
.role = role;
}
@Override
public
String toString(){
StringBuilder sb =
new
StringBuilder();
sb.append(
"***** Employee Details *****n"
);
sb.append(
"ID="
+getId()+
"n"
);
sb.append(
"Name="
+getName()+
"n"
);
sb.append(
"Permanent="
+isPermanent()+
"n"
);
sb.append(
"Role="
+getRole()+
"n"
);
sb.append(
"Phone Numbers="
+Arrays.toString(getPhoneNumbers())+
"n"
);
sb.append(
"Address="
+getAddress()+
"n"
);
sb.append(
"Cities="
+Arrays.toString(getCities().toArray())+
"n"
);
sb.append(
"Properties="
+getProperties()+
"n"
);
sb.append(
"*****************************"
);
return
sb.toString();
}
public
List
return
cities;
}
public
void
setCities(List
this
.cities = cities;
}
public
Map
return
properties;
}
public
void
setProperties(Map
this
.properties = properties;
}
}
|
Address.java
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
30
31
32
|
package
com.journaldev.json.model;
public
class
Address {
private
String street;
private
String city;
private
int
zipcode;
public
String getStreet() {
return
street;
}
public
void
setStreet(String street) {
this
.street = street;
}
public
String getCity() {
return
city;
}
public
void
setCity(String city) {
this
.city = city;
}
public
int
getZipcode() {
return
zipcode;
}
public
void
setZipcode(
int
zipcode) {
this
.zipcode = zipcode;
}
@Override
public
String toString(){
return
getStreet() +
", "
+getCity()+
", "
+getZipcode();
}
}
|
下面是Java程序,展示了如何将JSON转换为Java对象,反之亦然。
EmployeeGsonExample.java
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package
com.journaldev.json.gson;
import
java.io.IOException;
import
java.nio.file.Files;
import
java.nio.file.Paths;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
com.google.gson.Gson;
import
com.google.gson.GsonBuilder;
import
com.journaldev.json.model.Address;
import
com.journaldev.json.model.Employee;
public
class
EmployeeGsonExample {
public
static
void
main(String[] args)
throws
IOException {
Employee emp = createEmployee();
// Get Gson object
Gson gson =
new
GsonBuilder().setPrettyPrinting().create();
// read JSON file data as String
String fileData =
new
String(Files.readAllBytes(Paths
.get(
"employee.txt"
)));
// parse json string to object
Employee emp1 = gson.fromJson(fileData, Employee.
class
);
// print object data
System.out.println(
"nnEmployee Objectnn"
+ emp1);
// create JSON String from Object
String jsonEmp = gson.toJson(emp);
System.out.print(jsonEmp);
}
public
static
Employee createEmployee() {
Employee emp =
new
Employee();
emp.setId(
100
);
emp.setName(
"David"
);
emp.setPermanent(
false
);
emp.setPhoneNumbers(
new
long
[] {
123456
,
987654
});
emp.setRole(
"Manager"
);
Address add =
new
Address();
add.setCity(
"Bangalore"
);
add.setStreet(
"BTM 1st Stage"
);
add.setZipcode(
560100
);
emp.setAddress(add);
List
new
ArrayList
cities.add(
"Los Angeles"
);
cities.add(
"New York"
);
emp.setCities(cities);
Map
new
HashMap
props.put(
"salary"
,
"1000 Rs"
);
props.put(
"age"
,
"28 years"
);
emp.setProperties(props);
return
emp;
}
}
|
Gson是主类,它暴露出fromJson()和toJson()方法进行转换工作,对于默认实现,可以直接创建对象,也可以使用GsonBuilder类提供的实用选项进行转换,比如整齐打印,字段命名转换,排除字段,日期格式化,等等。
当运行以上程序时,可以看到以下Java对象的输出。
1
2
3
4
5
6
7
8
9
10
11
12
|
Employee Object
***** Employee Details *****
ID=100
Name=David
Permanent=
false
Role=Manager
Phone Numbers=[123456, 987654]
Address=BTM 1st Stage, Bangalore, 560100
Cities=[Los Angeles, New York]
Properties={age=28 years, salary=1000 Rs}
*****************************
|
你可以看到,使用Gson是多么的容易,这就是为什么它在JSON处理方面如此风靡。
以上的JSON处理方式是我们所熟知的对象模型,因为整个JSON被一次性的转换为对象了,在大多数情况下这足够了,然而如果JSON确实非常庞大,我们不想将其全部一次性置入内存,Gson也提供了Streaming API。
我们来看一个例子,它展示了如何使用Streaming API进行JSON到Java对象的转换。
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
package
com.journaldev.json.gson;
import
java.io.FileInputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
com.google.gson.stream.JsonReader;
import
com.google.gson.stream.JsonToken;
import
com.journaldev.json.model.Address;
import
com.journaldev.json.model.Employee;
public
class
EmployeeGsonReader {
public
static
void
main(String[] args)
throws
IOException {
InputStream is =
new
FileInputStream(
"employee.txt"
);
InputStreamReader isr =
new
InputStreamReader(is);
//create JsonReader object
JsonReader reader =
new
JsonReader(isr);
//create objects
Employee emp =
new
Employee();
Address add =
new
Address();
emp.setAddress(add);
List
new
ArrayList
emp.setCities(
new
ArrayList
emp.setProperties(
new
HashMap
String key =
null
;
boolean
insidePropertiesObj=
false
;
key = parseJSON(reader, emp, phoneNums, key, insidePropertiesObj);
long
[] nums =
new
long
[phoneNums.size()];
int
index =
0
;
for
(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
reader.close();
//print employee object
System.out.println(
"Employee Objectnn"
+emp);
}
private
static
String parseJSON(JsonReader reader, Employee emp,
List
boolean
insidePropertiesObj)
throws
IOException {
//loop to read all tokens
while
(reader.hasNext()){
//get next token
JsonToken token = reader.peek();
switch
(token){
case
BEGIN_OBJECT:
reader.beginObject();
if
(
"address"
.equals(key) ||
"properties"
.equals(key)){
while
(reader.hasNext()){
parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
}
reader.endObject();
}
break
;
case
END_OBJECT:
reader.endObject();
if
(insidePropertiesObj) insidePropertiesObj=
false
;
break
;
case
BEGIN_ARRAY:
reader.beginArray();
if
(
"phoneNumbers"
.equals(key) ||
"cities"
.equals(key)){
while
(reader.hasNext()){
parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
}
reader.endArray();
}
break
;
case
END_ARRAY:
reader.endArray();
break
;
case
NAME:
key = reader.nextName();
if
(
"properties"
.equals(key)) insidePropertiesObj=
true
;
break
;
case
BOOLEAN:
if
(
"permanent"
.equals(key)) emp.setPermanent(reader.nextBoolean());
else
{
System.out.println(
"Unknown item found with key="
+key);
//skip value to ignore it
reader.skipValue();
}
break
;
case
NUMBER:
if
(
"empID"
.equals(key)) emp.setId(reader.nextInt());
else
if
(
"phoneNumbers"
.equals(key)) phoneNums.add(reader.nextLong());
else
if
(
"zipcode"
.equals(key)) emp.getAddress().setZipcode(reader.nextInt());
else
{
System.out.println(
"Unknown item found with key="
+key);
//skip value to ignore it
reader.skipValue();
}
break
;
|