摘要:json(javascript object notation) 是一种轻量级的数据交换格式。它基于ecmascript的一个子集。 json采用完全独立于语言的文本格式,但是也使用了类似于c语言家族的习惯(包括c、c++、c#、java、javascript、perl、python等)。这些特性使json成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(网络传输速率)。
一、准备工作
json是个非常重要的数据结构,在web开发中应用十分广泛。我觉得每个人都应该好好的去研究一下json的底层实现,分析一下json的相关内容,希望大家能有所收获。首先给大家说一下使用json前的准备工作,需要准备下面的六个jar包:
需要说明几点:
(1)json-lib最新版本可以从这个地方下载:http://sourceforge.net/projects/json-lib/files/json-lib/
(2)ezmorph是一个简单的java类库,用于将一种bean转换成另外一种bean。其动态bean的实现依赖于commons-beanutils包。ezmorph可以在这个地方下载源码:http://sourceforge.net/projects/ezmorph/files/ezmorph/
(3)commons-beanutils是操作java bean的类库,依赖于commons-collections。可以从这里下载:http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi
(4)commons-collections类库是各种集合类和集合工具类的封装。可以从这里下载:http://commons.apache.org/proper/commons-collections/download_collections.cgi
二、语法相关
json 语法规则
json 语法是 javascript 对象表示法语法的子集。
数据在名称/值对中
数据由逗号分隔
花括号保存对象
方括号保存数组
json 值
json 值可以是:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在方括号中)
对象(在花括号中)
null
json有两种表示结构
对象和数组。
对象结构以”{”大括号开始,以”}”大括号结束。中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如代码。
1
|
2
3
4
5
|
{
key1:value1,
key2:value2,
...
}
|
如
1.{"department":"产品研发","name":"小王","age":23}
其中关键字是字符串,而值可以是字符串,数值,true,false,null,对象或数组
数组结构以”[”开始,”]”结束。中间由0或多个以”,”分隔的值列表组成,语法结构如代码。
1
|
2
3
4
5
6
7
8
9
10
|
[
{
key1:value1,
key2:value2
},
{
key3:value3,
key4:value4
}
]
|
如:
1
|
|
[{ "department" : "产品研发" , "name" : "小王" , "age" : 23 },{ "department" : "产品研发" , "name" : "小王" , "age" : 23 }]
|
三、java中使用json基本使用方法
整个工程目录 如下 :
employer.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
|
package com.bjpowernode.json;
import net.sf.json.jsonstring;
public class employer {
private string name;
private integer age;
private string department;
public string getname() {
return name;
}
public void setname(string name) {
this .name = name;
}
public integer getage() {
return age;
}
public void setage(integer age) {
this .age = age;
}
public string getdepartment() {
return department;
}
public void setdepartment(string department) {
this .department = department;
}
@override
public string tostring() {
return "employer [name=" + name + ", age=" + age + ", department="
+ department + "]" ;
}
/* @override 要调用这个方法请implements jsonstring
public string tojsonstring() {
return "{\"name\":\"" + name + "\",\"department\":\"" + department + "\"}";
}*/
}
|
jsontest.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
|
package com.bjpowernode.json;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import net.sf.json.jsonarray;
import net.sf.json.jsonobject;
import net.sf.json.jsonconfig;
import net.sf.json.util.propertyfilter;
/**
*json使用方法总结
*@author linbingwen(博客: http://blog.csdn.net/evankaka )
*@since 2015.7.3
*/
public class jsontest {
public static void main(string args[]){
beantojson();
beantojson1();
beantojson2();
arraytojson();
listtojson();
maptojson();
}
/**
* bean对象转json
* @return void
*/
public static void beantojson(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonobject json = jsonobject.fromobject(employer);
system.out.println( "-----------------------------------------beantojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson() 结束------------------------------------------------" );
}
/**
* bean对象转json,带过滤器
* @return void
*/
public static void beantojson1(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonconfig jsonconfig = new jsonconfig();
jsonconfig.setexcludes( new string[]
{ "age" });
jsonobject json = jsonobject.fromobject(employer, jsonconfig);
system.out.println( "-----------------------------------------beantojson1()带过滤器 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson1()带过滤器 结束------------------------------------------------" );
}
/**
* bean对象转json,带过滤器
* @return void
*/
public static void beantojson2(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonconfig jsonconfig = new jsonconfig();
jsonconfig.setjsonpropertyfilter( new propertyfilter() {
public boolean apply(object source, string name, object value)
{
return source instanceof employer && name.equals( "age" );
}
});
jsonobject json = jsonobject.fromobject(employer, jsonconfig);
system.out.println( "-----------------------------------------beantojson2() 带过滤器 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson2() 带过滤器 结束------------------------------------------------" );
}
/**
* array对象转json
* @return void
*/
public static void arraytojson(){
employer employer1= new employer();
employer1.setname( "小王" );
employer1.setage( 23 );
employer1.setdepartment( "产品研发" );
employer employer2= new employer();
employer2.setname( "小王" );
employer2.setage( 23 );
employer2.setdepartment( "产品研发" );
employer[] employers= new employer[]{employer1,employer2};
jsonarray json = jsonarray.fromobject(employers);
system.out.println( "-----------------------------------------arraytojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------arraytojson() 结束------------------------------------------------" );
}
/**
* list对象转json
* @return void
*/
public static void listtojson(){
list<string> list = new arraylist<string>();
list.add( "first" );
list.add( "second" );
jsonarray json = jsonarray.fromobject(list);
system.out.println( "-----------------------------------------listtojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------listtojson() 结束------------------------------------------------" );
}
/**
* map对象转json
* @return void
*/
public static void maptojson(){
map<object,object> map = new hashmap<object,object>();
map.put( "name" , "json" );
map.put( "bool" , boolean . true );
map.put( "int" , new integer( 1 ));
map.put( "arr" , new string[] { "a" , "b" });
map.put( "func" , "function(i){ return this.arr[i]; }" );
jsonobject json = jsonobject.fromobject(map);
system.out.println( "-----------------------------------------maptojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------maptojson() 结束------------------------------------------------" );
}
}
|
下面分别对各个部分来进行说明
1. bean转换成json代码
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* bean对象转json
* @return void
*/
public static void beantojson(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonobject json = jsonobject.fromobject(employer);
system.out.println( "-----------------------------------------beantojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson() 结束------------------------------------------------" );
}
|
运行结果如下:
2. 数组转换成json代码
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/**
* array对象转json
* @return void
*/
public static void arraytojson(){
employer employer1= new employer();
employer1.setname( "小王" );
employer1.setage( 23 );
employer1.setdepartment( "产品研发" );
employer employer2= new employer();
employer2.setname( "小王" );
employer2.setage( 23 );
employer2.setdepartment( "产品研发" );
employer[] employers= new employer[]{employer1,employer2};
jsonarray json = jsonarray.fromobject(employers);
system.out.println( "-----------------------------------------arraytojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------arraytojson() 结束------------------------------------------------" );
}
|
运行结果如下:
3. list集合转换成json方法
1
|
2
3
4
5
6
7
8
9
10
11
12
13
|
/**
* list对象转json
* @return void
*/
public static void listtojson(){
list<string> list = new arraylist<string>();
list.add( "first" );
list.add( "second" );
jsonarray json = jsonarray.fromobject(list);
system.out.println( "-----------------------------------------listtojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------listtojson() 结束------------------------------------------------" );
}
|
运行结果如下:
4. map集合转换成json方法
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* map对象转json
* @return void
*/
public static void maptojson(){
map<object,object> map = new hashmap<object,object>();
map.put( "name" , "json" );
map.put( "bool" , boolean . true );
map.put( "int" , new integer( 1 ));
map.put( "arr" , new string[] { "a" , "b" });
map.put( "func" , "function(i){ return this.arr[i]; }" );
jsonobject json = jsonobject.fromobject(map);
system.out.println( "-----------------------------------------maptojson() 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------maptojson() 结束------------------------------------------------" );
}
|
运行结果如下:
四、jsonobject的过滤设置
通常对一个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
|
package com.bjpowernode.json;
public class employer {
private string name;
private integer age;
private string department;
public string getname() {
return name;
}
public void setname(string name) {
this .name = name;
}
public integer getage() {
return age;
}
public void setage(integer age) {
this .age = age;
}
public string getdepartment() {
return department;
}
public void setdepartment(string department) {
this .department = department;
}
@override
public string tostring() {
return "employer [name=" + name + ", age=" + age + ", department="
+ department + "]" ;
}
}
|
如果我想过滤age属性怎么办?
方法一:实现jsonstring接口
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
|
package com.bjpowernode.json;
import net.sf.json.jsonstring;
public class employer implements jsonstring{
private string name;
private integer age;
private string department;
public string getname() {
return name;
}
public void setname(string name) {
this .name = name;
}
public integer getage() {
return age;
}
public void setage(integer age) {
this .age = age;
}
public string getdepartment() {
return department;
}
public void setdepartment(string department) {
this .department = department;
}
@override
public string tostring() {
return "employer [name=" + name + ", age=" + age + ", department="
+ department + "]" ;
}
@override
public string tojsonstring() {
return "{\"name\":\"" + name + "\",\"department\":\"" + department + "\"}" ;
}
}
|
方法二:设置jsonconfig实例,对包含和需要排除的属性进行添加或删除。
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/**
* bean对象转json,带过滤器
* @return void
*/
public static void beantojson1(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonconfig jsonconfig = new jsonconfig();
jsonconfig.setexcludes( new string[]
{ "age" });
jsonobject json = jsonobject.fromobject(employer, jsonconfig);
system.out.println( "-----------------------------------------beantojson1()带过滤器 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson1()带过滤器 结束------------------------------------------------" );
}
|
方法三:使用propertyfilter实例过滤属性
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* bean对象转json,带过滤器
* @return void
*/
public static void beantojson2(){
employer employer= new employer();
employer.setname( "小王" );
employer.setage( 23 );
employer.setdepartment( "产品研发" );
jsonconfig jsonconfig = new jsonconfig();
jsonconfig.setjsonpropertyfilter( new propertyfilter() {
public boolean apply(object source, string name, object value)
{
return source instanceof employer && name.equals( "age" );
}
});
jsonobject json = jsonobject.fromobject(employer, jsonconfig);
system.out.println( "-----------------------------------------beantojson2() 带过滤器 开始------------------------------------------------" );
system.out.println(json.tostring());
system.out.println( "-----------------------------------------beantojson2() 带过滤器 结束------------------------------------------------" );
}
|
五、javascript中使用json
json 最常见的用法之一,是从 web 服务器上读取 json 数据(作为文件或作为 httprequest),将 json 数据转换为 javascript 对象,然后在网页中使用该数据。
之前我一直有个困惑,分不清普通字符串
1、json字符串和json对象的区别。
字符串:这个很好解释,指使用“”双引号或''单引号包括的字符。例如:var comstr = 'this is string';
json字符串:指的是符合json格式要求的js字符串。例如:var jsonstr = "{studentid:'100',name:'tmac',hometown:'usa'}";
json对象:指符合json格式要求的js对象。例如:var jsonobj = { studentid: "100", name: "tmac", hometown: "usa" };
2、json 实例 - 来自字符串的对象
创建包含 json 语法的 javascript 字符串:
1
|
2
3
4
|
var txt = '{ "employees" : [' +
'{ "firstname":"john" , "lastname":"doe" },' +
'{ "firstname":"anna" , "lastname":"smith" },' +
'{ "firstname":"peter" , "lastname":"jones" } ]}' ;
|
由于 json 语法是 javascript 语法的子集,javascript 函数 eval() 可用于将 json 文本转换为 javascript 对象。eval() 函数使用的是 javascript 编译器,可解析 json 文本,然后生成 javascript 对象。必须把文本包围在括号中,这样才能避免语法错误:
1
|
|
var obj = eval ( "(" + txt + ")" );
|
如下格式:
1
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!doctype html>
<html>
<body>
<h2>create object from json string</h2>
<p>
first name: <span id= "fname" ></span><br>
last name: <span id= "lname" ></span><br>
</p>
<script>
var txt = '{"employees":[' +
'{"firstname":"john","lastname":"doe" },' +
'{"firstname":"anna","lastname":"smith" },' +
'{"firstname":"peter","lastname":"jones" }]}' ;
var obj = eval ( "(" + txt + ")" );
document.getelementbyid( "fname" ).innerhtml=obj.employees[ 1 ].firstname
document.getelementbyid( "lname" ).innerhtml=obj.employees[ 1 ].lastname
</script>
</body>
</html>
|
输出结果:
不过eval解析json有安全隐患!现在大多数浏览器(ie8及以上,chrome和firefox差不多全部)自带原生json对象,提供json.parse()方法解析json,提供json.stringify()方法生成json,请使用这两个方法!
如果担心parse()对对象抛异常,可以加一个封装函数:
1
|
2
3
4
5
6
7
|
json.pparse = function( tar ) {
if ( typeof( tar ) === 'string' ) {
return json.parse( tar );
} else {
return tar;
}
};
|
1、从json中读数据
1
|
2
3
4
5
6
7
8
|
//1,从json中读数据
function readjson() {
alert(obj.key1);
alert(obj.key2);
alert(obj.person[ 0 ].name); //或者alert(obj.person[0]["name"])
alert(obj.object.msg); //或者alert(obj.object["msg"])
}
|
2、增加json中的数据
1
|
2
3
4
5
|
function add() {
//往json对象中增加了一条记录
obj.sex= "男" //或者obj["sex"]="男"
alert(obj.sex);
}
|
3、更新json中的数据
1
|
2
3
|
function update() {
obj.count = 10 ; //或obj["count"]=10
}
|
4、删除json中的数据
1
|
2
3
4
5
6
7
8
9
|
function delete() {
delete obj.count;
}
、遍历json中的数据
function traversal() {
for (var c in obj) {
console.log(c + ":" , obj[c]);
}
}
|
六、xml与json对比
xml定义
扩展标记语言 (extensible markup language, xml),用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。xml使用dtd(document type definition)文档类型定义来组织数据;?格式统一,跨平台和语言,早已成为业界公认的标准。
xml是标准通用标记语言(sgml) 的子集,非常适合web 传输。xml提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
json定义
json(javascript object notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。json采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于c语言的习惯(包括c, c++, c#, java, javascript, perl, python等)体系的行为。这些特性使json成为理想的数据交换语言。
json基于javascript programming language , standard ecma-262 3rd edition - december 1999的一个子集。
xml和json优缺点
(1).xml的优缺点
<1>.xml的优点
a.格式统一,符合标准;
b.容易与其他系统进行远程交互,数据共享比较方便。
<2>.xml的缺点
a.xml文件庞大,文件格式复杂,传输占带宽;
b.服务器端和客户端都需要花费大量代码来解析xml,导致服务器端和客户端代码变得异常复杂且不易维护;
c.客户端不同浏览器之间解析xml的方式不一致,需要重复编写很多代码;d.服务器端和客户端解析xml花费较多的资源和时间。
json的优缺点
<1>.json的优点:
a.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小;b.易于解析,客户端javascript可以简单的通过eval()进行json数据的读取;c.支持多种语言,包括actionscript, c, c#, coldfusion, java, javascript, perl, php, python, ruby等服务器端语言,便于服务器端的解析;d.在php世界,已经有php-json和json-php出现了,偏于php序列化后的程序直接调用,php服务器端的对象、数组等能直接生成json格式,便于客户端的访问提取;e.因为json格式能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,且完成任务不变,并且易于维护。
<2>.json的缺点
a.没有xml格式这么推广的深入人心和喜用广泛,没有xml那么通用性;
b.json格式目前在web service中推广还属于初级阶段。