资讯专栏INFORMATION COLUMN

煦涵说JSON

lowett / 359人阅读

摘要:对象表示法,是一种数据交换格式,能够在服务器端交换数据,年由提出,目的是取代繁琐笨重的格式。煦涵煦涵煦涵煦涵煦涵参考文档感谢您的阅读作者煦涵年月日下面是实验室的微信公众号二维码,欢迎长按扫描关注

JSON(Javascript Object Notaion, javascript 对象表示法), 是一种数据交换格式,能够在服务器端交换数据, 2001年由Douglas Crockford提出,目的是取代繁琐笨重的XML格式。

JSON 数据格式的优点:

与语言无关的文本数据格式

轻量、简单、易维护

是javascript编程语言的一个子集(Standard ECMA-262 3rd Edition - December 1999), 符合javascript 语言语法,可以使用javascript提供的方法直接解析处理

JSON 建立在两种数据结构上:

键 / 值对:各种语言中可以为 字符串、对象、数组或者哈希表

有序列表(值):各种语言中实现为数组、向量、列表或者序列

JSON的基本语法:

JSON 对象

{
    "key": "value"
}

JSON 数组

["value", "value", "value"]

value 可取值

可以是 String(必须使用双引号包裹)、Number、Boolean、null、Object、Array, 这些形式可以嵌套,value值不能是八进制、十六进制(0xF0F)、undefined、function、日期对象,看下面示例:

合格的 JSON 格式:

{ 
    "name": "煦涵", 
    "name": null, 
    "male": true, 
    "age": 23
}

{ 
    "brother": ["煦涵1", "煦涵2"]
}

{ 
    "brother": {
        "煦涵1": {
            "age": 32
        },
        "煦涵2": {
            "age": 30
        }
    }
}

[{
    "name": "煦涵"
    "age": 30
},{
    "name": "张三"
    "age": 27
}]

不合格的 JSON 格式:

// key 必须用双引号包裹,value 如果是字符串必须用双引号包裹

{ "name": "煦涵" } 
[1, 2, 3, 4, oxFOF] 
{ "name": undefined } 
{ 
    "name": function() { 
        return "煦涵"
    } 
}
{ "name": new Date() }  

如果value的一个String(双引号包围)内包含 "/f u001f 需要使用反斜杠
如果value的一个Number,不能使用八进制和十六进制数值
PS: value对空格没有限制要求

JSON 对象

聊完 JSON 下面我们来聊聊 JSON 对象,javascript 在 ES5中新增了 JSON 对象,用来处理 JSON 文本数据,实现字符串与 JSON 对象间的相互转换,JSON.stringify ( value [ , replacer [ , space ] ] )JSON.parse ( text [ , reviver ] ), 前者是把 JSON 对象转换为 JSON 字符串,后者的把 JSON 字符串解析为 JSON 对象,下面来详细看看这个两个方法。

JSON.stringify ( value [ , replacer [ , space ] ] )

第一个参数: Value 必须项,可以是 Object, Array, String, Boolean, Number, Null.看几个例子:

JSON.stringify({
    "name": "煦涵",
    "age" : 28,
    "male" : true,
    "brother": [1, 2, 3],
    "parent": {
        "father" : {
            "name": "name"
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
})

// result
"{"name":"煦涵","age":28,"male":true,"brother":["B1","B2","B3"],"parent":{"father":{"name":"name"},"mother":{"name":"name"}},"other":null}" 

当待转换值不是 JSON 的基本类型时:

原始对象 item 值是 undefined、函数或 XML 对象,值会被过滤;

数组 item 是 undefined、函数或 XML 对象,值会被转成 null;

正则对象会被转换成空对象;

对象的不可遍历属性会被忽略;

八进制和十六进制会被转换成十进制;

特殊字符需要转义成反斜杠

JSON.stringify({
    "name": undefined,
    "age" : function() {return 28},
    "male" : /male/g,
    "brother": [undefined, function() {return abc}, "B3", 0xFOF],
    "parent": {
        "father" : {
            "name": undefined
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
})

// result: 正则被转出了空对象,undefined, function 被忽略或者转成 null

"{"male":{},"brother":[null,null,"B3", 3855],"parent":{"father":{},"mother":{"name":"name"}},"other":null}"

/* 不可遍历属性 */
var demo = {};
Object.defineProperties(demo, {
    "name": {
        value: "煦涵",
        enumerable: false
    },
    "age": {
        value: 28,
        enumerable: true
    }
})
JSON.stringify(demo);

// enumerable: 当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中,
// result: name 属性会被过滤
"{"age":28}"

/* 特殊字符处理-01 */
JSON.stringify({
    "special01": "回车 
,换行 
,退格 ,换页 f,Tab 	",
    "special02": "双引号 ",单引号 ", 斜杠 /, 反斜杠 ",
    "special03": "unicdoe字符 u001f"
})

// result
"{"special01":"回车 
,换行 
,退格 ,换页 f,Tab 	","special02":"双引号 ",单引号 ", 斜杠 /, 反斜杠 ","special03":"unicdoe字符 u001f"}"

/* 特殊字符处理-02 */
var demo = {}
demo.special01 = "回车 
,换行 
,退格 ,换页 f,Tab 	";
demo.special02 = "双引号 ",斜杠 /, 反斜杠,end ";
demo.special03 = "unicdoe字符 u001f";
JSON.stringify(demo);

// result, 双引号被转义了,反斜杠被忽略了
"{"special01":"回车 
,换行 
,退格 ,换页 f,Tab 	","special02":"双引号 ",斜杠 /, 反斜杠,end ","special03":"unicdoe字符 u001f"}"

第二个参数:replacer可选项,可以是 array or function

当replacer 是数组时,对第一个参数 value进行过滤,key 不在数组里的不会输出,这里需要注意的是,当第一个参数为Object时才有效,如果为Array,无效,看下面例子:

当replacer 是函数时,递归遍历所有的键,可以对对象进行format and replace 等操作

/* replacer 为数组 */
JSON.stringify({
    "0": "安徽省",
    "1": "蚌埠市",
    "2": "固镇县"
}, [0,1])
// result:
"{"0":"安徽省","1":"蚌埠市"}"

JSON.stringify([
    "安徽省",
    "蚌埠市",
    "固镇县"
], [0,1])

// result
"["安徽省","蚌埠市","固镇县"]"


/* replacer 为函数 */
JSON.stringify({
    "0": "安徽省",
    "1": "蚌埠市",
    "2": "固镇县"
}, function(key, value) {
    // key: "", value: {0: "安徽省", 1: "蚌埠市", 2: "固镇县"}
    console.log(key, value);
    return value[0] + value[1] + value[2];
})
// result
""安徽省蚌埠市固镇县""

第三个参数:space 可选项,用于增加format字符的可读性,可取值 Number, String, 但长度不超过10个字符

JSON.stringify({"name": "煦涵", "age": 28, "male": true, "other": null}, "", 4)

// result 
"{
    "name": "煦涵",
    "age": 28,
    "male": true,
    "other": null
}"

JSON.stringify({"level1": {"level2": {"level3": {"name": "煦涵"} } } }, "", "|---")

// result: 展示属性结构很直观
"{
|---"level1": {
|---|---"level2": {
|---|---|---"level3": {
|---|---|---|---"name": "煦涵"
|---|---|---}
|---|---}
|---}
}"

特殊情况
还记得上面的几种情况吧,当对象不是原始对象时,处理方式有所不同,比如正则表达式时,会返回空对象,日期对象时返回日期字符串;参看文档是,JSON.stringify发现参数对象有toJSON方法,就直接使用这个方法的返回值作为参数,而忽略原对象的其他参数。

JSON.stringify({
    "name": "煦涵",
    "age": 28,
    "toJSON": function() {
        return this.name + "年龄是" + this.age + "岁"
    }
})
// result:
""煦涵年龄是28岁""

/* 日期对象Date原型上包含toJSON 方法,`Date.prototype.toJSON ( key )` */
var date = new Date();
date.toJSON();
JSON.stringify(date);

/* RegExp 对象 JSON.stringify 默认会把正则转换成空对象,我们可以使用toJSON, 把正则表达式转换成字符串 */
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/abc/g)
// result
""/abc/g""
JSON.parse ( text [ , reviver ] )

JSON.parse为 JSON.stringify的逆运算,转换时 text 必须符合JSON的语法格式, 不然会报错,reviver 参数 和 JSON.stringify 的参数 replacer类似, 但是遍历顺序和replacer相反。

JSON.parse("{"name":"煦涵","age":28,"male":true,"brother":["B1","B2","B3"],"parent":{"father":{"name":"name"},"mother":{"name":"name"}},"other":null}" )

/* result:
{
    "name": "煦涵",
    "age" : 28,
    "male" : true,
    "brother": ["B1", "B2", "B3"],
    "parent": {
        "father" : {
            "name": "name"
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
}
*/

JSON.parse("{"level1": {"level2": {"name": "煦涵"} } }", function(key, value) {
    // level2 Object {name: "煦涵"}
    // level1 Object {level2: Object}
    // Object {level1: Object}
    console.log(key, value);
    return value;
})

// result
{"level1":{"level2":{"name":"煦涵"}}}
参考文档:

http://www.ecma-international.org/ecma-262/5.1/#sec-15.12
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
http://www.json.org/

感谢您的阅读

--eof--

作者[煦涵]
2017年04月30日

下面是「FED实验室」的微信公众号二维码,欢迎长按、扫描关注:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83220.html

相关文章

  • 涵说Babel

    摘要:,下一代编译器,当前版本,它可以处理的所有新语法,并内置了扩展及类型注解支持,如果对不是很了解可以查看实验室微信公众号文章煦涵说。 Babel,下一代javascript编译器,当前版本 v2.4.0 ,它可以处理ES6的所有新语法,并内置了React JSX扩展及Flow类型注解支持,如果对Flow不是很了解可以查看FED实验室微信公众号文章煦涵说Flow。 Babel与JavaSc...

    lordharrd 评论0 收藏0
  • 涵说Flow

    摘要:现在已经在前端比较流行的等框架中得到使用。今天煦涵就和大家一起来学习以及在实际项目中的使用。安装这里我们选择使用,当前你也可以使用如果你对不是很了解,建议你阅读煦涵说。 Flow是Facebook出品的一个JavaScript代码的静态类型检查工具,它做了很多处理,使您的代码更快,更智能,更自信,更好的适应性。现在已经在前端比较流行的React 、Vue 等框架中得到使用。今天煦涵就和...

    王伟廷 评论0 收藏0
  • 涵说Yarn

    摘要:是一个新的包管理器,它由开发者共同开发完成。从包管理器中借鉴,创建了文件,用来记录项目使用每个包的确切版本。感谢您的阅读作者煦涵年月日下面是实验室的微信公众号二维码,欢迎长按扫描关注 Yarn是一个新的Javascript包管理器,它由Facebook, Google, Exponent and Tilde开发者共同开发完成。Yarn 不是 NPM 的fork版本,而是它的重新设计,Y...

    pkhope 评论0 收藏0
  • 涵说Webpack-IE低版本兼容指南

    摘要:,是一个前端资源加载打包工具,现在版本已经到,今天的文章不支持介绍的及使用,而是对最近项目开发中使用打包时处理低版本及以下浏览器兼容问题做一次总结。 Webpack,Webpack 是一个前端资源加载/打包工具,现在版本已经 release 到 v2.6.1,今天的文章不支持介绍Webpack的API及使用,而是对最近项目开发中使用Webpack打包时处理IE低版本(IE8及以下)浏览...

    tanglijun 评论0 收藏0
  • #干货盘点#JSON-C API

    摘要:什么是对象简谱是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。 什么是Json​ Json(JavaScript Object Notation,JS 对象简谱)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。一些合法的Json实例:键值对:(可以没有键只有值)键 ...

    codeGoogle 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<