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 相关文章推荐
prototype1.4中文手册
Sep 22 Javascript
JavaScript 滚轮事件使用说明
Mar 07 Javascript
字符串的replace方法应用浅析
Dec 06 Javascript
json中换行符的处理方法示例介绍
Jun 10 Javascript
jQuery窗口、文档、网页各种高度的精确理解
Jul 02 Javascript
jQuery中DOM树操作之使用反向插入方法实例分析
Jan 23 Javascript
11种ASP连接数据库的方法
Sep 18 Javascript
Bootstrap每天必学之级联下拉菜单
Mar 27 Javascript
javacript获取当前屏幕大小
Jun 04 Javascript
JS刷新父窗口的几种方式小结(推荐)
Nov 09 Javascript
echarts设置图例颜色和地图底色的方法实例
Aug 01 Javascript
Jquery的autocomplete插件用法及参数讲解
Mar 12 jQuery
简易的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
使用MaxMind 根据IP地址对访问者定位
2006/10/09 PHP
php源码加密 仿微盾PHP加密专家(PHPCodeLock)
2010/05/06 PHP
解析PHPExcel使用的常用说明以及把PHPExcel整合进CI框架的介绍
2013/06/24 PHP
浅谈PHP中Stream(流)
2015/06/08 PHP
PHP children()函数讲解
2019/02/03 PHP
一个通过script自定义属性传递配置参数的方法
2014/09/15 Javascript
NodeJS中利用Promise来封装异步函数
2015/02/25 NodeJs
JavaScript职责链模式概述
2016/09/17 Javascript
jQuery实现表格与ckeckbox的全选与单选功能
2016/11/24 Javascript
js中编码函数:escape,encodeURI与encodeURIComponent详解
2017/03/21 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
JS实现验证码倒计时的注册页面
2018/01/02 Javascript
通过jquery的ajax请求本地的json文件方法
2018/08/08 jQuery
详解如何为你的angular app构建一个第三方库
2018/12/07 Javascript
Layui Table js 模拟选中checkbox的例子
2019/09/03 Javascript
Vue3项目打包后部署到服务器 请求不到后台接口解决方法
2020/02/06 Javascript
VUE前端从后台请求过来的数据进行转换数据结构操作
2020/11/11 Javascript
[58:11]守擂赛第二周擂主赛 DeMonsTer vs Leopard
2020/04/28 DOTA
在Python中使用元类的教程
2015/04/28 Python
Windows下python2.7.8安装图文教程
2016/05/26 Python
python3爬取各类天气信息
2018/02/24 Python
对PyTorch torch.stack的实例讲解
2018/07/30 Python
详解Python中的type和object
2018/08/15 Python
python列表使用实现名字管理系统
2019/01/30 Python
Python Django框架实现应用添加logging日志操作示例
2019/05/17 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
Keras loss函数剖析
2020/07/06 Python
python中Django文件上传方法详解
2020/08/05 Python
谷歌浏览器小字体处理方案即12px以下字体
2013/12/17 HTML / CSS
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
汽车维修专业毕业生的求职信分享
2013/12/04 职场文书
公务员党的群众路线教育实践活动学习心得体会
2014/10/30 职场文书
理想国读书笔记
2015/06/25 职场文书
新郎父亲婚礼致辞
2015/07/27 职场文书
医院消毒隔离制度
2015/08/05 职场文书