JSON是JavaScript Object Notation的缩写,它是一种数据交换格式。
在JSON出现之前,大家一直用XML来传递数据。因为XML是一种纯文本格式,所以它适合在网络上交换数据。XML本身不算复杂,但是,加上DTD、XSD、XPath、XSLT等一大堆复杂的规范以后,任何正常的软件开发人员碰到XML都会感觉头大了,最后大家发现,即使你努力钻研几个月,也未必搞得清楚XML的规范。
终于,在2002年的一天,道格拉斯·克罗克福特(Douglas Crockford)同学为了拯救深陷水深火热同时又被某几个巨型软件企业长期愚弄的软件工程师,发明了JSON这种超轻量级的数据交换格式。
道格拉斯同学长期担任雅虎的高级架构师,自然钟情于JavaScript。他设计的JSON实际上是JavaScript的一个子集。在JSON中,一共就这么几种数据类型:
- number:和JavaScript的number完全一致;
- boolean:就是JavaScript的true或false;
- string:就是JavaScript的string;
- null:就是JavaScript的null;
- array:就是JavaScript的Array表示方式——[];
- object:就是JavaScript的{...}表示方式。
以及上面的任意组合。
并且,JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号”“,Object的键也必须用双引号”“。
由于JSON非常简单,很快就风靡Web世界,并且成为ECMA标准。几乎所有编程语言都有解析JSON的库,而在JavaScript中,我们可以直接使用JSON,因为JavaScript内置了JSON的解析。
把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能够通过网络传递给其他计算机。如果我们收到一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用这个对象了。
让我们先把小明这个对象序列化成JSON格式的字符串:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
JSON.stringify(xiaoming);
在chrome浏览器的console中运行上面代码,输出结果如下:
"{"name":"小明","age":14,"gender":true,"height":1.65,"grade":null,"middle-school":"\"W3C\" Middle School","skills":["JavaScript","Java","Python","Lisp"]}"
要输出得好看一些,可以加上参数,按缩进输出:
JSON.stringify(xiaoming, null, ' ');
结果:
"{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}"
第二个参数用于控制如何筛选对象的键值,如果我们只想输出指定的属性,可以传入Array:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
结果:
"{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}"
还可以传入一个函数,这样对象的每个键值对都会被函数先处理:
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringify(xiaoming, convert, ' ');
结果:
"{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" MIDDLE SCHOOL",
"skills": [
"JAVASCRIPT",
"JAVA",
"PYTHON",
"LISP"
]
}"
如果我们还想要精确控制如何序列化小明,可以给xiaoming定义一个toJSON()的方法,直接返回JSON应该序列化的数据:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只输出name和age,并且改变了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
拿到一个JSON格式的字符串,我们直接用JSON.parse()把它变成一个JavaScript对象:
JSON.parse('[1,2,3,true]'); // Array [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
//还可以接收一个函数,用来转换解析出的属性:
JSON.parse('{"name":"小明","age":14}', function (key, value) {
// 把number * 2:
if (key === 'name') {
return value + '同学';
}
return value;
}); // Object {name: '小明同学', age: 14}
在JavaScript中使用JSON,就是这么简单!
在数据传输流程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键。
JSON对象是直接可以使用JQuery操作的格式,和js中的对象一样,可以用对象(类名)点出属性(方法)。JSON字符串仅仅只是一个字符串,一个整体,不截取的话没办法取出其中存储的数据,不能直接使用,除非你只想alert()它。
JSON字符串:
var str1 = '{ "name": "haorooms", "sex": "man" }';
JSON对象:
var str2 = { "name": "haorooms", "sex": "man" };
读取JSON对象的属性值:
var str2 = { "name": "haorooms", "sex": "man" };
alert(str2.name);
//弹出” haorooms”
//对于复杂一点的JSON对象
var str={"GetUserPostByIdResult":{"Age":"33","ID":"2server","Name":"haorooms"}};
alert(str.GetUserPostByIdResult.Name); //弹出haorooms
对于JSON字符串,如果想像上面那样自如的读取其属性,必须运用下面的方法将JSON字符串领先转化为JSON对象(这一点在ajax返回的时候,经常遇到!):
var str = '{ "name": "haorooms", "sex": "man" }';
//方法1
var obj1 = eval('(' + str + ')'); //Object {name: "haorooms", sex: "man"}
//方法2
var obj2 = JSON.parse(str); //Object {name: "haorooms", sex: "man"}
作为后台人员,与数据库交互、处理业务逻辑已经驾轻就熟,但与前端合作就显得不是那么熟练了。举一个例子,一个用户列表,我们从数据库取出来是一个List
刚刚接触网站开发可能都会出现类似的问题,我们是多希望前端和后台的工作分的清清楚楚啊!其实不用想那么复杂,JSON就可以帮我们!后台只需告诉前端,请求某一个URL地址就可以得到用户数据的JSON格式的数据,前端在需要的时候自己去请求就好,剩下的工作就由前端做就好了,清楚干净!
代码实例:
/**
* 测试获取所有用户列表
* @param request
* @return String
* @throws IOException
*/
@RequestMapping("/getAllUserTest")
public String getAllUserTest(HttpServletRequest request, HttpServletResponse response) throws IOException {
//从数据库中取出所有用户信息,返回值为一个User对象集合,每个User对象包含username与age两个参数
List findAll = userService.findAll();
//创建JSONArray实例
JSONArray jsonArray = new JSONArray();
//for each循环取出每个User对象
for(User user: findAll) {
//JSONObject是一个{}包裹起来的一个对象(Object),
//JSONArray则是[]包裹起来的一个数组(Array)
//此处为对象,所以用得到JSONObject
JSONObject jo = new JSONObject();
jo.put("username", user.getUsername());
jo.put("age", user.getAge());
jsonArray.add(jo);
}
try {
//后台输出测试
System.out.println(jsonArray.toString());
//设置字符集
response.setCharacterEncoding("UTF-8");
//页面输出
response.getWriter().println("JSON输出形式:");
response.getWriter().write(jsonArray.toString());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
那么前端请求相应的URL就可以得到所有的用户信息了!效果如下:
前台的数据如何通过JSON这种数据交换格式传入后台?
(1)将要传入后台的数据组装成JSON格式的字符串
var data = [{'name':'jim' , 'age':20} , {'name':'king' , 'age':26},{'name':'jge' , 'age':30}];
var jsonString = JSON.stringify(data);
(2)使用jQuery的ajax请求向后台传数据
$.ajax({
type: "post",
url: url,
dataType : 'json',
data : {'mydata':jsonString},
success: function(data,textStatus){
alert("操作成功");
},
error: function(xhr,status,errMsg){
alert("操作失败!");
}
});
(3)后台接收数据并解析
String jsonString = ServletActionContext.getRequest().getParameter("mydata");
JSONArray jsonArray = JSONArray.fromObject(jsonString);
for(int i = 0;i < jsonArray.length(); i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i);
jsonObj.getInt("name");
jsonObj.getString("age");
}