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 相关文章推荐
Javascript 解疑
Nov 11 Javascript
加载 Javascript 最佳实践
Oct 30 Javascript
动态加载JS文件的三种方法
Nov 08 Javascript
分享28款免费实用的 JQuery 图片和内容滑块插件
Dec 15 Javascript
jQuery的remove()方法使用详解
Aug 11 Javascript
js实现微信分享代码
Oct 11 Javascript
JQ中$(window).load和$(document).ready区别与执行顺序
Mar 01 Javascript
详解使用nvm管理多版本node的方法
Aug 30 Javascript
微信小程序开发常见问题及解决方案
Jul 11 Javascript
解决layui的使用以及针对select、radio等表单组件不显示的问题
Sep 05 Javascript
JS中自定义事件的使用与触发操作实例分析
Nov 01 Javascript
javascript浅层克隆、深度克隆对比及实例解析
Feb 09 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
全国FM电台频率大全 - 7 吉林省
2020/03/11 无线电
PHP用户指南-cookies部分
2006/10/09 PHP
PHP实现通过中文字符比率来判断垃圾评论的方法
2014/10/20 PHP
Laravel 5框架学习之Eloquent 关系
2015/04/09 PHP
php ajax异步读取rss文档数据
2016/03/29 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
PHP删除数组中特定元素的两种方法
2019/02/28 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
浅谈php常用的7大框架的优缺点
2020/07/20 PHP
事件冒泡是什么如何用jquery阻止事件冒泡
2013/03/20 Javascript
图片无缝滚动代码(向左/向下/向上)
2013/04/10 Javascript
jquery取消选择select下拉框示例代码
2014/02/22 Javascript
jquery自动填充勾选框即把勾选框打上true
2014/03/24 Javascript
js检验密码强度(低中高)附图
2014/06/05 Javascript
一句jQuery代码实现返回顶部效果(简单实用)
2016/12/28 Javascript
原生js实现新闻列表展开/收起全文功能
2017/01/20 Javascript
vue指令以及dom操作详解
2017/03/04 Javascript
jquery tmpl模板(实例讲解)
2017/09/02 jQuery
javascript实现最长公共子序列实例代码
2018/02/05 Javascript
妙用缓存调用链实现JS方法的重载
2018/04/30 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
JavaScript实现无限级递归树的示例代码
2019/03/29 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
2019/07/10 Javascript
node.js基于dgram数据报模块创建UDP服务器和客户端操作示例
2020/02/12 Javascript
详解ES6实现类的私有变量的几种写法
2021/02/10 Javascript
[01:52]DOTA2完美大师赛Vega战队趣味视频——kpii老师小课堂
2017/11/25 DOTA
[40:03]Liquid vs Optic 2018国际邀请赛淘汰赛BO3 第一场 8.21
2018/08/22 DOTA
Python找出最小的K个数实例代码
2018/01/04 Python
python爬虫刷访问量 2019 7月
2019/08/01 Python
python palywright库基本使用
2021/01/21 Python
退伍老兵事迹材料
2014/01/31 职场文书
低碳生活倡议书
2014/04/14 职场文书
导师推荐信范文
2014/05/09 职场文书
升职感谢信
2015/01/22 职场文书
员工工作表现自我评价
2015/03/06 职场文书
2015年学校关工委工作总结
2015/04/03 职场文书