首先需要明确的是JSON即JavaScript 对象表示法(JavaScript Object Notation),JSON是一种用于交换结构化数据的文本格式,而不是一种编程语言,类似于XML,但是JSON 比 XML 更小、更快,更易解析,目的是取代繁琐笨重的XML格式。
1. 一种数据格式
什么是格式?就是规范你的数据要怎么表示,举个栗子,有个人叫“二百六”,身高“160cm”,体重“60kg”,现在你要将这个人的这些信息传给别人或者别的什么东西,你有很多种选择:
姓名“二百六”,身高“160cm”,体重“60kg”
name="二百六"&height="160cm"&weight="60kg"
{"name":"二百六","height":160,"weight":60}
以上所有选择,传递的数据是一样的,但是你可以看到形式是可以各式各样的,这就是各种不同格式化后的数据,JSON是其中一种表示方式。
2. 基于文本的数据格式
JSON是基于文本的数据格式,相对于基于二进制的数据,所以JSON在传递的时候是传递符合JSON这种格式(至于JSON的格式是什么我们第二部分再说)的字符串,我们常会称为“JSON字符串”。
3. 轻量级的数据格式
在JSON之前,有一个数据格式叫xml
,现在还是广泛在用,但是JSON更加轻量,如xml
需要用到很多标签,即相同数据,以JSON的格式占据的带宽更小,这在有大量数据请求和传递的情况下是有明显优势的。
4. 被广泛地用于数据交换
轻量已经是一个用于数据交换的优势了,但更重要的JSON是易于阅读、编写和机器解析的,即这个JSON对人和机器都是友好的,而且又轻,独立于语言(因为是基于文本的),所以JSON被广泛用于数据交换。
以前端JS进行ajax的POST请求为例,后端JAVA处理请求为例:
前端构造一个JS对象,用于包装要传递的数据,然后将JS对象转化为JSON字符串,再发送请求到后端;
后端JAVA接收到这个JSON字符串,将JSON字符串转化为JAVA中的pojo对象,然后处理请求。
可以看到,相同的数据在这里有3种不同的表现形式,分别是前端的JS对象、传输的JSON字符串、后端的JAVA中的pojo对象,JS对象和JAVA对象明显不是一个东西,但是由于大家用的都是JSON来传递数据,大家都能理解这种数据格式,都能把JSON这种数据格式很容易地转化为自己能理解的数据结构,这就方便啦,在其他各种语言环境中交换数据都是如此。
1. JSON与js对象的区别
JSON(JavaScript Object Notation)仅仅是一种数据格式(或者叫数据形式)。数据格式其实就是一种规范,按照这种规范来存诸和交换数据。就好像 XML 格式一样。
区别 | Json | Javascript对象 |
---|---|---|
含义 | 仅仅是一种数据格式 | 对象的实例 |
传输 | 可以跨平台数据传输,速度快 | 不能传输 |
表现 | 1. 键值对 2. 键必须加双引号 3. 值可以是数字(整数或浮点数)、字符串(在双引号中)、逻辑值(true 或 false)、数组(在方括号中)、对象(在花括号中)、null;不能为方法函数/undefined/NaN |
1.键值对 2.值可以是函数、对象、字符串、数字、boolean 等 |
相互转换 | Json → JS 对象: 1. var obj = JSON.parse(jsonstring); 2. var obj = eval("("+jsonstring+")"); |
JS 对象 → Json:JSON.stringify(obj); |
JSON 文本格式在语法上与创建 JavaScript 对象的代码相同,但本质是不同的。我们不能把以下的对象叫 JSON,比如:
var obj1 = {}; // 这只是 JS 对象
// 可把这个称做:JSON 格式的 JavaScript 对象
var obj2 = {"width":100,"height":200,"name":"rose"};
// 可把这个称做:JSON 格式的字符串
var str1 = '{"width":100,"height":200,"name":"rose"}';
// 这个可叫 JSON 格式的数组,是 JSON 的稍复杂一点的形式
var arr = [
{"width":100,"height":200,"name":"rose"},
{"width":100,"height":200,"name":"rose"},
{"width":100,"height":200,"name":"rose"},
];
// 这个可叫稍复杂一点的 JSON 格式的字符串
var str2='['+
'{"width":100,"height":200,"name":"rose"},'+
'{"width":100,"height":200,"name":"rose"},'+
'{"width":100,"height":200,"name":"rose"},'+
']';
2. 两个本质不同的东西为什么那么密切
JSON和JS对象本质上完全不是同一个东西,就像“斑马线”和“斑马”,“斑马线”基于“斑马”身上的条纹来呈现和命名,但是斑马是活的,斑马线是非生物。同样,JSON 本身的意思就是 JavaScript 对象表示法(JavaScript Object Notation),可以说这种数据格式是从 JavaScript 对象中演变出来的,但它就是一种格式,而JS对象是一个实例,是存在于内存的一个东西。此外,JSON 格式的数据,主要是为了跨平台交流数据用的。JSON 独立于语言和平台,JSON 解析器和 JSON 库支持许多不同的编程语言。JSON是可以传输的,因为它是文本格式,但是JS对象是没办法传输的,js对象只有在序列化JSON格式的字符串后才能传输。
JSON
对象包含两个方法: 用于解析JSON格式字符串为JavaScript对象的JSON.parse(data)方法,以及将JavaScript对象转换为 JSON格式字符串的JSON.stringify(data)方法。
JavaScript对象实现序列化——JSON.stringify(data):
函数签名如下:
JSON.stringify(value[, replacer [, space]])
第一个参数可以是SON格式的JS对象或者数组;第二个参数可以是函数或者数组;第三个参数用于美化输出格式的,一般没有什么用,在这就不做介绍。
注意:
1. 如果第二个参数是一个函数,那么序列化过程中的每个属性都会被这个函数转化和处理,这个函数必须对每一项都有返回,这个函数接受两个参数,一个键名,一个是属性值,函数必须针对每一个原来的属性值都要有新属性值的返回。
2. 如果第二个参数是一个数组,只有在数组中出现的属性才会被序列化进结果字符串,只要在这个提供的数组中找不到的属性就不会被包含进去,而这个数组中存在但是源JS对象中不存在的属性会被忽略,不会报错。
实例
1. 仅传入一个参数
传入一个JSON格式的JS对象或者数组:
JSON.stringify({"name":"Good Man","age":18}),
返回一个字符串"{"name":"Good Man","age":18}"
。
2. 传入两个参数,第一个参数是JS对象或者数组,第二个参数是函数
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":"1234567",
"age":18
};
var friendAfter=JSON.stringify(friend,function(key,value){
if(key==="phone")
return "(000)"+value;
else if(typeof value === "number")
return value + 10;
else
return value; //如果你把这个else分句删除,那么结果会是undefined
});
console.log(friendAfter);
//输出:{"firstName":"Good","lastName":"Man","phone":"(000)1234567","age":28}
3. 传入两个参数,第一个参数是JS对象或者数组,第二个参数若是数组
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":"1234567",
"age":18
};
//注意下面的数组有一个值并不是上面对象的任何一个属性名
var friendAfter=JSON.stringify(friend,["firstName","address","phone"]);
console.log(friendAfter);
//{"firstName":"Good","phone":"1234567"}
//指定的“address”由于没有在原来的对象中找到而被忽略
4. JSON.stringify(data)函数其他特性:
键名不是双引号的(包括没有引号或者是单引号),会自动变成双引号;字符串是单引号的,会自动变成双引号;
最后一个属性后面有逗号的,会被自动去掉;
非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中,这个好理解,也就是对非数组对象在最终字符串中不保证属性顺序和原来一致;
布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值;
JSON.stringify(new Boolean(true)) //"true"
JSON.stringify(new String('123')) //""123""
JSON.stringify(new Number(1)) //"1"
JSON.stringify(new Date()) //""2016-09-20T02:26:38.294Z""
如果对象的成员是undefined或函数,这个成员会被省略;如果数组的成员是undefined或函数,则这些值被转成null
JSON.stringify({ a: function(){}, b: undefined, c: [ function(){}, undefined ] }); // "{"c":[null,null]}"
5. 影响 JSON.stringify 的函数 —— object.toJSON
如果你在一个JS对象上实现了toJSON
方法,那么调用JSON.stringify
去序列化这个JS对象时,JSON.stringify
会把这个对象的toJSON
方法返回的值作为参数去进行序列化。
var info={
"msg":"I Love You",
"toJSON":function(){
var replaceMsg=new Object();
replaceMsg["msg"]="Go Die";
return replaceMsg;
}
};
JSON.stringify(info);
//出si了,返回的是:'"{"msg":"Go Die"}"',说好的忽略函数呢
这个函数就是这样子的。其实Date
类型可以直接传给JSON.stringify
做参数,其中的道理就是,Date
类型内置了toJSON
方法。
JSON格式字符串解析成JavaScript对象——JSON.parse(data):
函数签名如下:
JSON.parse(text[, reviver])
如果第一个参数,即JSON字符串不是合法的字符串的话,那么这个函数会抛出错误,所以如果你在写一个后端返回JSON字符串的脚本,最好调用语言本身的JSON字符串相关序列化函数,而如果是自己去拼接实现的序列化字符串,那么就尤其要注意序列化后的字符串是否是合法的,合法指这个JSON字符串完全符合JSON要求的严格格式。
JSON.parse()方法也可以接收一个函数参数,在每个键值对儿上调用,这个函数被称为还原函数(reviver)。该函数接收两个参数,一个键和一个值,返回一个值
如果还原函数返回undefined,则表示要从结果中删除相应的键;如果返回其他值,则将该值插入到结果中
var o = JSON.parse('{"a":1,"b":2}', function(key, value) {
if (key === ''){
return value;
}
if (key === 'a') {
return value + 10;
}
});
o.a // 11
o.b // undefined
在将日期字符串转换为Date对象时,经常要用到还原函数
var book = {
"title": "javascript",
"date": new Date(2016,9,1)
}
var jsonStr = JSON.stringify(book);
//'{"title":"javascript","date":"2016-09-30T16:00:00.000Z"}''
console.log(jsonStr)
var bookCopy = JSON.parse(jsonStr,function(key,value){
if(key == 'date'){
return new Date(value);
}
return value;
})
console.log(bookCopy.date.getFullYear());//2016
以springmvc为例顺带推荐处理json的两个工具类:
//映射路径
@RequestMapping(value = "/pingxing/articleindex.action")
//表示返回json格式字符串的注解
@ResponseBody
//获取前端传递的参数aoData
public String articleindex(String aoData,String objectToJson){
/*在maven工程的pom.xml中引入依赖
*/
//将获取的aoData通过JSONArray.fromObject(aoData);方法转为JSONArray类的对象。
JSONArray jsonarray=(JSONArray) JSONArray.fromObject(aoData);
Article article = JsonUtils.jsonToPojo(objectToJson, Article.class);
//然后遍历 jsonarray从json字符串中获取需要的值
for (int i = 0; i < jsonarray.size(); i++) {
JSONObject obj = (JSONObject) jsonarray.get(i);
if (obj.get("name").equals("sEcho"))
sEcho = obj.get("value").toString();
if (obj.get("name").equals("iDisplayStart"))
iDisplayStart =Integer.parseInt(obj.get("value").toString());
if (obj.get("name").equals("iDisplayLength"))
iDisplayLength = Integer.parseInt(obj.get("value").toString());
}
从数据库取值的代码。。。。。
JSONObject getObj = new JSONObject();
getObj.put("sEcho", sEcho);// DataTable前台必须要的
getObj.put("iTotalRecords",pageinfo.getTotal());
getObj.put("iTotalDisplayRecords",ArticleList.size());
getObj.put("data", ArticleList);
//返回JSON格式的字符串
return getObj.toString();
}