JSON对象 详解及实例代码


Posted in Javascript onOctober 18, 2016

前面的话

json(javascript object notation)全称是javascript对象表示法,它是一种数据交换的文本格式,而不是一种编程语言,用于读取结构化数据。2001年由Douglas Crockford提出,目的是取代繁琐笨重的XML格式。本文将详细介绍关于json的内容 

语法规则

JSON的语法可以表示以下三种类型的值

【1】简单值

简单值使用与JavaScript相同的语法,可以在JSON中表示字符串、数值、布尔值和null

字符串必须使用双引号表示,不能使用单引号。数值必须以十进制表示,且不能使用NaN和Infinity

[注意]JSON不支持JavaScript中的特殊值undefined

//合格的简单值
5
"hello world"
true
null
//不合格的简单值
+0x1
'hello world'
undefined
NaN
Infinity

【2】对象

对象作为一种复杂数据类型,表示的是一组有序的键值对儿。而每个键值对儿中的值可以是简单值,也可以是复杂数据类型的值

与javascript的对象字面量相比,json有三个不同的地方

1、JSON没有变量的概念

2、JSON中,对象的键名必须放在双引号里面

3、因为JSON不是javascript语句,所以没有末尾的分号

[注意]同一个对象中不应该出现两个同名属性

//合格的对象
{
  "name":"huochai",
  "age":29,
  "school":{
    "name":"diankeyuan",
    "location":"beijing"
  }
}
//不合格的对象
{ name: "张三", 'age': 32 }//属性名必须使用双引号
{};//不需要末尾的分号
{ "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
 "getName": function() {
   return this.name;
 }
} // 不能使用函数和日期对象

【3】数组

数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象或数组

JSON数组也没有变量和分号,把数组和对象结合起来,可以构成更复杂的数据集合

[注意]数组或对象最后一个成员的后面,不能加逗号

JSON对象

JSON之所以流行,是因为可以把JSON数据结构解析为有用的javascript对象

ECMAScript5对解析JSON的行为进行了规范,定义了全局对象JSON

[注意]IE7-浏览器不支持

JSON对象有两个方法:stringify()和parse()。这两个方法分别用于把JavaScript对象序列化为JSON字符串和把JSON字符串解析为原生JavaScript值

stringify()

JSON.stringify()方法用于将一个值转为字符串。该字符串应该符合JSON格式,并且可以被JSON.parse()方法还原 

默认情况下,JSON.stringify()输出的JSON字符串不包括任何空格字符或缩进

var jsonObj = {
  "title":"javascript",
  "group":{
    "name":"jia",
    "tel":12345
  }
};
//{"title":"javascript","group":{"name":"jia","tel":12345}}
JSON.stringify(jsonObj);

具体转换

JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"
JSON.stringify([1, "false", false])// '[1,"false",false]'
JSON.stringify({ name: "张三" })// '{"name":"张三"}'

stringify()方法把正则表达式和数学对象转换成空对象的字符串形式

JSON.stringify(/foo/) // "{}"
JSON.stringify(Math) // "{}"

stringify()方法把日期对象和包装对象转换成字符串

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]}"

JSON.stringify()方法会忽略对象的不可遍历属性

var obj = {};
Object.defineProperties(obj, {
 'foo': {
  value: 1,
  enumerable: true
 },
 'bar': {
  value: 2,
  enumerable: false
 }
});
JSON.stringify(obj); // {"foo":1}]

参数

JSON.stringify()除了要序列化的JavaScript对象外,还可以接收另外两个参数,这两个参数用于指定以不同的方式序列化JavaScript对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数;第二个参数是一个选项,表示是否在JSON字符串中保留缩进

【数组过滤器】

当stringify()方法的第二个参数是一个数组时,这时相当于实现一个过滤器的功能

【1】过滤器只对对象的第一层属性有效

var jsonObj = {
  "title":"javascript",
  "group":{
    "a":1
  }
};
//{"group":{"a":1}}
console.log(JSON.stringify(jsonObj,["group","a"]))

【2】过滤器对数组无效

var jsonObj =[1,2];
JSON.stringify(jsonObj,["0"])//"[1,2]"

【函数参数】

stringify()方法的第二个参数也可以是一个函数。传入的函数接收两个参数,属性(键)名和属性值

JSON.stringify({a:1,b:2}, function(key, value){
 if (typeof value === "number") {
  value = 2 * value;
 }
 return value;  
})
// "{"a":2,"b":4}"

属性名只能是字符串,而在值并非键值对儿结构的值时,键名可以是空字符串

这个函数参数会递归处理所有的键

下面代码中,对象o一共会被f函数处理三次。第一次键名为空,键值是整个对象o;第二次键名为a,键值是{b:1};第三次键名为b,键值为1

JSON.stringify({a: {b: 1}}, function (key, value) {
 console.log("["+ key +"]:" + value);
 return value;
})
// []:[object Object]
// [a]:[object Object]
// [b]:1
// '{"a":{"b":1}}'

函数返回的值就是相应键的值。如果函数返回了undefined或没有返回值,那么相应的属性会被忽略

JSON.stringify({ a: "abc", b: 123 }, function (key, value) {
 if (typeof(value) === "string") {
  return undefined;
 }
 return value;
})
// '{"b": 123}'

【缩进】

stringify()方法还可以接受第三个参数,用于增加返回的JSON字符串的可读性

如果是数字,表示每个属性前面添加的空格(最多不超过10个)

如果是字符串(不超过10个字符),则该字符串会添加在每行前面

/*"{
 "p1": 1,
 "p2": 2
}"*/
JSON.stringify({ p1: 1, p2: 2 }, null, 2);
//"{"p1":1,"p2":2}"
JSON.stringify({ p1: 1, p2: 2 }, null, 0);
/*"{
|-"p1": 1,
|-"p2": 2
}"*/
JSON.stringify({ p1:1, p2:2 }, null, '|-');
toJSON()

有时候,JSON.stringify()还是不能满足对某些对象进行自定义序列化的需求。在这些情况下, 可以通过对象上调用toJSON()方法,返回其自身的JSON数据格式

JSON.stringify({
 toJSON: function () {
  return "Cool"
 }
})
// ""Cool""
var o = {
 foo: 'foo',
 toJSON: function() {
  return 'bar';
 }
};
JSON.stringify({x: o});// '{"x":"bar"}'

如果toJSON()方法返回undefined,此时如果包含它的对象嵌入在另一个对象中,会导致该对象的值变成null。而如果包含它的对象是顶级对象,结果就是undefined

JSON.stringify({
 toJSON: function () {
  return undefined
 }
})
//undefined

Date对象部署了一个自己的toJSON方法,自动将Date对象转换成日期字符串

JSON.stringify(new Date("2016-08-29"))
// "2016-08-29T00:00:00.000Z"

toJSON方法的一个应用是,可以将正则对象自动转为字符串

RegExp.prototype.toJSON =RegExp.prototype.toString;
JSON.stringify(/foo/)// ""/foo/""

toJSON()可以作为函数过滤器的补充,因此理解序列化的内部顺序十分重要。假设把一个对象传入JSON.stringify(),序列化该对象的顺序如下

1、如果存在toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,按默认顺序执行序列化

2、如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第一步返回的值

3、对第二步返回的每个值进行相应的序列化

4、如果提供了第三个参数,执行相应的格式化

 

parse()

JSON.parse方法用于将JSON字符串转化成对象

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null
var o = JSON.parse('{"name": "张三"}');
o.name // 张三

如果传入的字符串不是有效的JSON格式,JSON.parse方法将报错

//Uncaught SyntaxError: Unexpected token u in JSON at position 0(…)
JSON.parse("'String'")

//Uncaught SyntaxError: Unexpected token u in JSON at position 0(…)
JSON.parse("undefined")

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 // undefinef

在将日期字符串转换为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

eval()

实际上,eval()类似于JSON.parse()方法,可以将json字符串转换为json对象

eval('(' + '{"a":1}'+')').a;//1
JSON.parse('{"a":1}').a;//1

但是,eval()可以执行不符合JSON格式的代码,有可能会包含恶意代码

eval('(' + '{"a":alert(1)}'+')').a;//弹出1
JSON.parse('{"a":alert(1)}').a;//报错

所以,还是要尽量少使用eval()

Javascript 相关文章推荐
JS Timing
Apr 21 Javascript
JS实现距离上次刷新已过多少秒示例
May 23 Javascript
JQuery 控制内容长度超出规定长度显示省略号
May 23 Javascript
基于JS实现的倒计时程序实例
Jul 24 Javascript
理解JavaScript中worker事件api
Dec 25 Javascript
html+js实现简单的计算器代码(加减乘除)
Jul 12 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
Sep 05 Javascript
vue实现todolist单页面应用
Apr 11 Javascript
微信小程序实战之仿android fragment可滑动底部导航栏(4)
Apr 16 Javascript
在Vue中如何使用Cookie操作实例
Jul 27 Javascript
JS实现的倒计时恢复按钮点击功能【可用于协议阅读倒计时】
Apr 19 Javascript
JavaScript两种计时器的实例讲解
Jan 31 Javascript
简易的JS计算器实现代码
Oct 18 #Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
Oct 18 #Javascript
jquery中用jsonp实现搜索框功能
Oct 18 #Javascript
JavaScript排序算法动画演示效果的实现方法
Oct 18 #Javascript
浅谈js的异步执行
Oct 18 #Javascript
Jquery AJAX POST与GET之间的区别详细介绍
Oct 17 #Javascript
微信小程序 教程之模块化
Oct 17 #Javascript
You might like
PHP 类商品秒杀计时实现代码
2010/05/05 PHP
php验证是否是md5编码的简单代码
2014/04/01 PHP
让CodeIgniter的ellipsize()支持中文截断的方法
2014/06/12 PHP
php的4种常见运行方式
2015/03/20 PHP
基于thinkPHP类的插入数据库操作功能示例
2017/01/06 PHP
PHP错误处理函数register_shutdown_function使用示例
2017/07/03 PHP
XHTML-Strict 内允许出现的标签
2006/12/11 Javascript
HTML node相关的一些资料整理
2010/01/01 Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
2012/01/15 Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
2013/04/19 Javascript
jquery 操作两个select实现值之间的互相传递
2014/03/07 Javascript
javascript中拼接HTML字符串的最快、最好的方法
2014/06/07 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
2015/06/10 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
微信小程序 Windows2008 R2服务器配置TLS1.2方法
2016/12/05 Javascript
整理一些最近经常遇到的前端面试题
2017/04/25 Javascript
vue页面跳转后返回原页面初始位置方法
2018/02/11 Javascript
nuxt踩坑之Vuex状态树的模块方式使用详解
2019/09/06 Javascript
javascript实现前端成语点击验证
2020/06/24 Javascript
python缩进区别分析
2014/02/15 Python
python采集博客中上传的QQ截图文件
2014/07/18 Python
Python实现的多线程端口扫描工具分享
2015/01/21 Python
python图像处理之反色实现方法
2015/05/30 Python
21行Python代码实现拼写检查器
2016/01/25 Python
Python with语句上下文管理器两种实现方法分析
2018/02/09 Python
基于Python开发chrome插件的方法分析
2018/07/07 Python
Python图像处理之图像的缩放、旋转与翻转实现方法示例
2019/01/04 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
pycharm激活码2020最新分享适用pycharm2020最新版亲测可用
2020/11/22 Python
使用css3做0.5px的细线的示例代码
2018/01/18 HTML / CSS
驴妈妈旅游网:中国新型的B2C旅游电子商务网站
2016/08/16 全球购物
Swisse官方海外旗舰店:澳大利亚销量领先,自然健康品牌
2017/12/15 全球购物
将一个文本文件的内容按倒序打印出来
2015/01/05 面试题
销售人员个人求职信
2013/09/26 职场文书
2015年乡镇工会工作总结
2015/05/19 职场文书
python的netCDF4批量处理NC格式文件的操作方法
2022/03/21 Python