转自:https://www.zifangsky.cn/561.html
一 介绍
在Java开发中,我们通常需要进行XML文档或JSON字符串的构造和解析。当然在Java Web开发中有一些第三方插件是可以自动完成Java对象和json之间的转换的,比如:jackson插件(PS:关于jackson的基本使用可以参考下我以前写过的这篇文章:https://www.zifangsky.cn/380.html)。
不过为了能够更好地理解json字符串的构造和解析,我将使用JSON-lib包来手动完成对json的构造和一些基本方法的使用。JSON-lib包中最关键的两个类分别是JSONObject和JSONArray,我们可以简单地将JSONObject这个类构造的字符串理解成Map集合;将JSONArray这个类构造的字符串理解成List集合或者数组。当然,关于它们的一些基本使用我将在下面详细介绍
要想使用JSON-lib来完成json字符串的构造或者解析工作,除了需要json-lib-2.4-jdk15.jar这个jar包之外,还需要以下几个依赖jar包:
- commons-beanutils-1.9.2.jar
- commons-collections-3.2.2.jar
- commons-lang-2.4.jar
- commons-logging-1.1.3.jar
- ezmorph-1.0.6.jar
当然,这几个jar包可以自行百度下载,也可以使用我用过的这几个jar包:http://pan.baidu.com/s/1hrGhTek
二 JSONObject的初步使用
(1)JSON字符串格式化:
在正式开始介绍json字符串的构造之前,我首先推荐一个在线的json格式化工具,可以将我们生成的json字符串格式化成比较直观的形式,便于我们查看,传送门:http://tool.oschina.net/codeformat/json
(2)JSON字符串的两种基本构造方法:
i)新建一个普通的Java工程,并导入上述的几个依赖包
ii)新建两个测试用的Java类:
Animal.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
|
package
cn
.
zifangsky
.
json
;
public
class
Animal
{
private
String
name
;
private
int
age
;
public
Animal
(
)
{
}
public
Animal
(
String
name
,
int
age
)
{
this
.
name
=
name
;
this
.
age
=
age
;
}
public
String
getName
(
)
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
int
getAge
(
)
{
return
age
;
}
public
void
setAge
(
int
age
)
{
this
.
age
=
age
;
}
}
|
User.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
cn
.
zifangsky
.
json
;
import
java
.
util
.
List
;
public
class
User
{
private
String
name
;
private
String
sex
;
private
int
age
;
private
String
contact
;
private
List
<Animal>
ownPet
;
public
User
(
)
{
}
public
User
(
String
name
,
String
sex
,
int
age
,
String
contact
,
List
<Animal>
ownPet
)
{
this
.
name
=
name
;
this
.
sex
=
sex
;
this
.
age
=
age
;
this
.
contact
=
contact
;
this
.
ownPet
=
ownPet
;
}
public
String
getName
(
)
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getSex
(
)
{
return
sex
;
}
public
void
setSex
(
String
sex
)
{
this
.
sex
=
sex
;
}
public
int
getAge
(
)
{
return
age
;
}
public
void
setAge
(
int
age
)
{
this
.
age
=
age
;
}
public
String
getContact
(
)
{
return
contact
;
}
public
void
setContact
(
String
contact
)
{
this
.
contact
=
contact
;
}
public
List
<Animal>
getOwnPet
(
)
{
return
ownPet
;
}
public
void
setOwnPet
(
List
<Animal>
ownPet
)
{
this
.
ownPet
=
ownPet
;
}
}
|
iii)一个json字符串构造实例:
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
|
package
cn
.
zifangsky
.
json
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
net
.
sf
.
json
.
JSONObject
;
public
class
JSONObjectDemo
{
/**
* 使用Map集合生成json字符串
* */
public
JSONObject
createJsonFromMap
(
Map
<
String
,
String
>
jMap
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
putAll
(
jMap
)
;
return
jObject
;
}
/**
* 使用一个Java对象生成json字符串
* */
public
JSONObject
createJsonFromObject
(
Object
object
)
{
return
JSONObject
.
fromObject
(
object
)
;
}
public
static
void
main
(
String
[
]
args
)
{
JSONObjectDemo
demo
=
new
JSONObjectDemo
(
)
;
Map
<
String
,
String
>
tMap
=
new
HashMap
<
String
,
String
>
(
)
;
tMap
.
put
(
"name"
,
"zifangsky"
)
;
tMap
.
put
(
"sex"
,
"male"
)
;
tMap
.
put
(
"age"
,
"1024"
)
;
tMap
.
put
(
"contact"
,
"https://www.zifangsky.cn"
)
;
JSONObject
jObject1
=
demo
.
createJsonFromMap
(
tMap
)
;
System
.
out
.
println
(
"createJsonFromMap: "
+
jObject1
)
;
System
.
out
.
println
(
"***************************"
)
;
// ********************************************
User
u
=
new
User
(
)
;
u
.
setName
(
"AlphaGo"
)
;
u
.
setAge
(
10
)
;
Animal
dog
=
new
Animal
(
"旺财"
,
5
)
;
Animal
cat
=
new
Animal
(
"九头猫妖"
,
2
)
;
List
<Animal>
pets
=
new
ArrayList
<Animal>
(
)
;
pets
.
add
(
dog
)
;
pets
.
add
(
cat
)
;
u
.
setOwnPet
(
pets
)
;
JSONObject
jObject2
=
demo
.
createJsonFromObject
(
u
)
;
System
.
out
.
println
(
"createJsonFromObject: "
+
jObject2
)
;
}
}
|
输出如下:
1
2
3
|
createJsonFromMap:
{
"sex"
:
"male"
,
"contact"
:
"https://www.zifangsky.cn"
,
"name"
:
"zifangsky"
,
"age"
:
"1024"
}
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
createJsonFromObject
:
{
"ownPet"
:
[
{
"name"
:
"旺财"
,
"age"
:
5
}
,
{
"name"
:
"九头猫妖"
,
"age"
:
2
}
]
,
"contact"
:
""
,
"sex"
:
""
,
"name"
:
"AlphaGo"
,
"age"
:
10
}
|
当然,我们可以看出现在这种json字符串的格式不是很友好,我们不能很直观的看出整个json的内在逻辑构成,因此需要对它进行格式化。在使用了我上面推荐的在线工具进行格式化之后,这两个json字符串分别是这样的:
1
2
3
4
5
6
|
{
sex
:
"male"
,
contact
:
"https://www.zifangsky.cn"
,
name
:
"zifangsky"
,
age
:
"1024"
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
{
ownPet
:
[
{
name
:
"旺财"
,
age
:
5
}
,
{
name
:
"九头猫妖"
,
age
:
2
}
]
,
contact
:
""
,
sex
:
""
,
name
:
"AlphaGo"
,
age
:
10
}
|
这样就可以很清晰的看出整个json字符串的构成了。当然,上面生成json的代码都很简单,自己看一下就明白了,我这里就不多说了
三 JSONObject的几个常用方法以及对json字符串的解析实例
(1)JSONObject的put方法:
使用put方法可以在一个json中插入一个节点,如果该节点已经存在,那么该节点的值将会被替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* 使用put方法插入节点,如果该key下已经存在值则替换该值
* */
public
JSONObject
testPut
(
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
put
(
"1"
,
"put1"
)
;
jObject
.
put
(
"2"
,
"put2"
)
;
jObject
.
put
(
"3"
,
"put3"
)
;
Animal
bird
=
new
Animal
(
"bird"
,
1
)
;
jObject
.
put
(
"4"
,
bird
)
;
List
<String>
list
=
new
ArrayList
<String>
(
)
;
list
.
add
(
"string1"
)
;
list
.
add
(
"string2"
)
;
jObject
.
put
(
"string"
,
list
)
;
jObject
.
put
(
"5"
,
"put5"
)
;
jObject
.
put
(
"2"
,
"put6"
)
;
// jObject.put("string", true);
return
jObject
;
}
|
然后在主函数中调用执行该方法:
1
2
3
4
|
JSONObjectDemo2
demo2
=
new
JSONObjectDemo2
(
)
;
System
.
out
.
println
(
"put: "
+
demo2
.
testPut
(
)
)
;
System
.
out
.
println
(
)
;
|
对输出的json字符串进行格式化之后,该json的格式如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
1
:
"put1"
,
2
:
"put6"
,
3
:
"put3"
,
4
:
{
name
:
"bird"
,
age
:
1
}
,
5
:
"put5"
,
string
:
[
"string1"
,
"string2"
]
}
|
(2)JSONObject的accumulate方法:
对于accumulate方法,如果节点不存在时,那么accumulate方法将和put方法一样在json中插入一个新节点;如果是一个已经存在的节点,那么将会在该节点上累积此次的值,形成一个数组的形式
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
|
/**
* 使用accumulate方法可以在一个key下累积值
* 如果该key下存在值则值继续累积,形成一个数组
* 如果该key不存在则accumulate方法相当于put方法
* */
public
JSONObject
testAccumulate
(
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
put
(
"1"
,
"1"
)
;
jObject
.
put
(
"2"
,
2
)
;
jObject
.
put
(
"3"
,
3.3
)
;
jObject
.
accumulate
(
"1"
,
"1.11"
)
;
jObject
.
accumulate
(
"2"
,
false
)
;
Animal
dove
=
new
Animal
(
"stupid dove"
,
2
)
;
jObject
.
accumulate
(
"2"
,
dove
)
;
List
<String>
list
=
new
ArrayList
<String>
(
)
;
list
.
add
(
"arr1"
)
;
list
.
add
(
"arr2"
)
;
jObject
.
accumulate
(
"2"
,
list
)
;
jObject
.
accumulate
(
"4"
,
"4"
)
;
return
jObject
;
}
|
然后同样是在主函数中调用执行这个方法,最后对输出的json字符串进行格式化之后,该json的格式如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
{
1
:
[
"1"
,
"1.11"
]
,
2
:
[
2
,
false
,
{
name
:
"stupid dove"
,
age
:
2
}
,
[
"arr1"
,
"arr2"
]
]
,
3
:
3.3
,
4
:
"4"
}
|
(3)JSONObject的element方法:
据我所知,这个方法跟put方法的基本使用是一样的(PS:如果二者有使用不一样的,希望大家可以告诉我一下):
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/**
* element方法跟put方法的使用基本一样
* */
public
JSONObject
testElement
(
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
put
(
"1"
,
"1"
)
;
jObject
.
put
(
"2"
,
2
)
;
jObject
.
element
(
"2"
,
"2_element"
)
;
jObject
.
element
(
"3"
,
"333"
)
;
return
jObject
;
}
|
最后对输出的json字符串进行格式化之后,该json的格式如下所示:
1
2
3
4
5
|
{
1
:
"1"
,
2
:
"2_element"
,
3
:
"333"
}
|
(4)JSONArray的基本使用:
对于JSONObject和JSONArray这两个类,有的童鞋可能不是很明白二者的区别在哪里。其实很简单,JSONObject构造的字符串就像Map集合一样,是键值对的形式,即:Key:Value,多个键值对之间以英文逗号连接(PS:可以观察上面的那个json字符串)。于此同时,JSONArray构造的字符串就如List集合或者数组一样,是一个数组的形式,即:[array1,array2,array3 …]
比如说下面这个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/**
* JSONArray的基本使用
* 可以形成数组
* */
public
JSONObject
testJSONArray
(
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
put
(
"1"
,
"1"
)
;
jObject
.
put
(
"2"
,
2
)
;
jObject
.
put
(
"3"
,
3.3
)
;
JSONArray
jsonArray
=
new
JSONArray
(
)
;
jsonArray
.
add
(
"arr1"
)
;
jsonArray
.
add
(
"arr2"
)
;
jObject
.
put
(
"array"
,
jsonArray
)
;
return
jObject
;
}
|
对输出的json字符串进行格式化之后,该json的格式如下所示:
1
2
3
4
5
6
7
8
9
|
{
1
:
"1"
,
2
:
2
,
3
:
3.3
,
array
:
[
"arr1"
,
"arr2"
]
}
|
从上面的json字符串可以看出,array这个键对应的值是一个JSONArray,也就是一个数组的形式
(5)解析json字符串实例:
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
|
/**
* 解析json字符串
* */
public
void
testGetValue
(
)
{
JSONObject
jObject
=
new
JSONObject
(
)
;
jObject
.
put
(
"1"
,
"1"
)
;
jObject
.
put
(
"2"
,
2
)
;
jObject
.
accumulate
(
"1"
,
"1.11"
)
;
jObject
.
accumulate
(
"2"
,
false
)
;
Animal
dove
=
new
Animal
(
"stupid dove"
,
2
)
;
jObject
.
accumulate
(
"2"
,
dove
)
;
jObject
.
element
(
"3"
,
"3"
)
;
System
.
out
.
println
(
jObject
)
;
// 根据key取对应的字符串
String
value
=
jObject
.
getString
(
"2"
)
;
System
.
out
.
println
(
value
)
;
// 将字符串转换成一个JSONArray
JSONArray
jsonArray
=
JSONArray
.
fromObject
(
value
)
;
String
doveString
=
String
.
valueOf
(
jsonArray
.
get
(
2
)
)
;
//取数组中第三个字符串
System
.
out
.
println
(
doveString
)
;
// 将一个字符串转换成JSONObject
JSONObject
jsonObject_dove
=
JSONObject
.
fromObject
(
doveString
)
;
// 根据key取值
System
.
out
.
println
(
"doveName: "
+
jsonObject_dove
.
getString
(
"name"
)
)
;
System
.
out
.
println
(
"age: "
+
jsonObject_dove
.
getInt
(
"age"
)
)
;
}
|
输出如下:
1
2
3
4
5
|
{
"1"
:
[
"1"
,
"1.11"
]
,
"2"
:
[
2
,
false
,
{
"name"
:
"stupid dove"
,
"age"
:
2
}
]
,
"3"
:
"3"
}
[
2
,
false
,
{
"name"
:
"stupid dove"
,
"age"
:
2
}
]
{
"name"
:
"stupid dove"
,
"age"
:
2
}
doveName
:
stupid
dove
age
:
2
|
其中,第一次输出是初始json字符串构造完成之后,将这个json字符串格式化之后是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
1
:
[
"1"
,
"1.11"
]
,
2
:
[
2
,
false
,
{
name
:
"stupid dove"
,
age
:
2
}
]
,
3
:
"3"
}
|
然后,在这个json中取出了键为“2”的json字符串,此时出现第二次输出:
1
2
3
4
5
6
7
8
|
[
2
,
false
,
{
name
:
"stupid dove"
,
age
:
2
}
]
|
从前面我介绍的JSONArray概念可以得知,这个字符串是可以构造成一个JSONArray类型的对象的。在构造完成之后,又取出了这个数组中的第三个值,此时得到了第三次的输出:
1
2
3
4
|
{
name
:
"stupid dove"
,
age
:
2
}
|
同理,对于这个字符串我们是可以转换成JSONObject对象的。最后就是根据键取出对应的值,此时出现最后的输出:
1
2
|
doveName
:
stupid
dove
age
:
2
|