你不知道的JSON
JSON的历史
Douglas Crockford 是JSON的创造者,也是JavaScript:the good part的作者。
JSON(JavaScript Object Notation)是一种由Douglas Crockford 构想和设计、轻量级的数据交换语言 ,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript 的一个子集,但JSON是独立于语言的文本格式 ,并且采用了类似于C语言 家族的一些习惯。
JSON格式是1999年《JavaScript Programming Language, Standard ECMA-262 3rd Edition》的子集合,所以可以在JavaScript 以eval()
函数(javascript通过eval()调用解析器)读入。不过这并不代表JSON无法使用于其他语言,事实上几乎所有与网页开发相关的语言都有JSON函数库。
JSON是Douglas Crockford在2001年开始推广使用的数据格式,在2005年-2006年正式成为主流的数据格式,雅虎和谷歌就在那时候开始广泛地使用JSON格式。
什么是JSON( JavaScript Object Notation)
JSON是一种数据交换格式。
JSON独立于编程语言。
JSON不局限于某项技术,本身非私有,且可移植。对于产生(序列化)和读取(反序列化)JSON 数据,所有的现代编程语言(Java、JavaScript、Ruby、C#、PHP、Python、Groovy等)和平台都提供了良好的支持。
可以说,我们使用的是一种基于对象表示法的数据交换格式,JSON 表达数据的方式对通用的编程概念都很友好。
为什么使用JSON:
基于 JSON 的 RESTful API 的爆发式增长
JSON 基本数据结构的简洁性
JSON 非常简洁,并且正在逐步替代 XML 成为互联网上主要的数据交换格式。它易于阅读,相关结构也很容易与软件开发人员所熟悉的概念对应起来,精简的数据类型也便于程序员理解,如数组、对象和名称 - 值对。
由于节省了每个数据元素的开始标签与结束标签,JSON 格式的额外开销更少、更为紧凑,所以JSON 格式的文档一般比内容相同的 XML 文档小。从企业级应用的角度来看,与 XML 相比,JSON 文档在网络上的传输与处理更快,因此效率更高。
如今 JSON 在配置文件领域也占有一席之地。后面会将与其他配置文件的区别。
JSON语法
JSON包含3种核心数据类型:
名称-值对:由一个名称(数据属性)和一个值组成。
对象:名称 - 值对的无序集合。
数组:值的有序集合。
键始终被双引号包围,当值是字符串时,必须使用双引号。
JSON 中的名称 - 值对是一种对许多系统都十分友好的数据结构,而使用空格和特殊字符(即 a-z、0-9 除外的其他字符)忽略了可移植性。我们在第 1 章中将这一专业术语定义为“以一种双方系统都兼容的方式在平台间传递信息”。如果我们这么做的话,会直接降低 JSON 数据的可移植性;因此我们说,为了获得最大可移植性,应尽可能避免使用空格或特殊字符。
JSON 中的名称 - 值对的名称如果被系统作为对象装入内存的话,将会成为“属性”。在部分系统中,属性名可以包含下划线( _ )或数字,但是大多数情况下最好是使用英文字母 A
Z 或 az,在含有多个单词时,最好使用驼峰表示法。例子:”Lindsay’s animal”:”cat”
JSON数据类型
JSON中的数据类型:
在字符串中需要转义的字符:
- 双引号
- 反斜杠
- / (正斜线)
- \b (退格符)
- \f (换页符)
- \t (制表符)
- \n (换行符)
- \r (回车符)
- \u 后面跟十六进制字符(如笑脸表情 \u263A )
JSON中的数字
数字
- 整型
- 浮点数
- 定点数 —— 计算机中采用的一种数的表示方法。参与运算的数的小数点位置固定不变 。
数字需要注意:
- 数值永远是十进制数(只能出现数字 0~9),不能以 0 开头。
- 数值可以存在由小数点( . )开头的小数部分。
- 数值可以是以 10 为底的指数,该指数由 e 或 E 来表示,其后跟正号表示正指数幂,跟
负号则表示负指数幂。 - 数值不支持八进制数和十六进制数。
- 与 JavaScript 不同,数值不能是 NaN(Not a Number,用于表示非法数值),也不能是
Infinity
没有注释
一言以蔽之,JSON 中没有注释。
根据 Crockford 在 Yahoo! JSON group 和 Google+ 上的说法,JSON 最开始是允许出现注释的,但之后不久就因为以下原因移除了注释。
Crockford 认为注释没有什么用处。
JSON 解析器在支持注释方面存在困难。
出现了滥用注释的情况。Crockford 发现有些注释被用于解析指令,而这会彻底摧毁
JSON 的互操作性。移除注释有利于 JSON 实现跨平台性,简化这方面的支持工作。
没有注释意味着我们需要更语义化的命名,或者给要描述的对象添加一个描述字段。没有注释是JSON的一个相对于有注释数据格式在可读性方面的一个劣势。
JSON风格指南
google的一份风格指南。
选择有意义的属性名
- 属性名应该是具有定义语义的有意义的名称。
- 属性名必须是驼峰式的,ASCII码字符串。
- 首字符必须是字母,下划线(_)或美元符号($)。
- 随后的其他字符可以是字母,数字,下划线(_)或美元符号($)。
- 应该避免使用Javascript中的保留关键字(下文附有Javascript保留字清单)
数组类型应该是复数属性名。其它属性名都应该是单数。
数组通常包含多个条目,复数属性名就反映了这点。在下面这个保留名称中可以看到例子。属性名items是复数因为它描述的是一组对象。大多数的其它字段是单数。
考虑移除空或null值
如果一个属性是可选的或者包含空值或null值,考虑从JSON中去掉该属性,除非它的存在有很强的语义原因。
枚举值应当以字符串的形式呈现
随着APIs的发展,枚举值可能被添加,移除或者改变。将枚举值当作字符串可以使下游用户幽雅地处理枚举值的变更。
通过选择新的属性名或将API版本化来避免命名冲突
新的属性可在将来被添加进保留列表中。JSON中不存在命名空间。如果存在命名冲突,可通过选择新的属性名或者版本化来解决这个问题。
JavaScript保留字应该避免在属性名中使用
JSON结构和保留属性名
其他特性
语法验证。
工具:JSON Formatter & Validator 可视化工具,会展示树形结构。
[JSON Editor Online](http://www.jsoneditoronline.org/) [JSONLint](http://jsonlint.com/)
以上这些都是语法验证工具。我们会在之后讨论另一种类型的验证——一致性验证。语法验证关注的是 JSON 的格式,而一致性验证关注的是其独特的数据结构。
JSON的媒体格式
JSON 的 MIME 类型是 application/json 。
序列化和反序列化。
JSON从2009年的 ECMAScript 5 标准开始成为 JavaScript 原生类库的一部分。
在之前使用eval()这个函数来执行序列化。
使用 JSON.stringify() 和 JSON.parse() 进行 JavaScript 中的序列化 / 反序列化操作。
其他的语言也有序列化和反序列化的库。
JSON作为配置文件
选择配置文件的考量:可读性,方便被编程语言/框架解析。
软件中经常会有配置文件或设置文件,它让我们可以不必重新编译就能修改设置。配置文件的格式有很多,有 INI ,yuml和 XML 等。
yuml和XML都是有注释的。
yuml除了支持JSON中的数据类型,还支持时间和日期这两种数据类型,相对于JSON,yaml的语法规则要稍微复杂一些,对于初学者来说,没有JSON那么好上手。
XML 能够包含更为复杂的数据,但是它不像 JSON 一样具有数据类型。
JSON和XML 还有另外一个很大的区别在于有效数据率。JSON作为数据包格式传输的时候具有更高的效率,这是因为JSON不像XML那样需要有严格的闭合标签,这就让有效数据量与总数据包比大大提升,从而减少同等数据流量的情况下,网络的传输压力
除了这些数据格式本身具有的优缺点外,是否能够很方便地被编程语言 / 框架解析也是一个很重要的考量因素。如果 JSON 解析器已经在你的应用中深度使用了,那么 JSON 可能是你配置文件的最佳选择。
JSON Schema 对数据进行验证(重点)语义校验
JSON Schema官网:http://json-schema.org/
JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.
JSON Schema是一个词汇表,允许您注释和验证JSON文档。它也是一个JSON文件,本身遵守JSON规范。
json-schema 的用途越来越广泛,除了定义数据结构外,我们还可以使用 json-schema 验证数据格式和生成随机数据 。
它可以验证的内容有:
值的数据类型是否正确?
可以具体规定一个值是数字、字符串等类型。
是否包含所需要的数据?
可以具体规定哪些数据是需要的,哪些是不需要的。
值的形式是不是我需要的?
可以指定范围、最小值和最大值。
如何使用Schema
首先,需要在 JSON 第一个名称 - 值对中,声明其为一个 schema 文件。
第二个名称 - 值对应该是 JSON Schema 文件的标题.
在 JSON Schema 文件的第三个名称值对中,要定义需要在 JSON 中包含的属性。
为了在 JSON Schema 中实现这一逻辑,需要在 “$schema” 、 “title” 和”properties” 后面加上第四个名称 - 值对,它的名称是 “required” ,值为一个数组。数组中包含必填的字段。
非常重要的一点是,如果你的 JSON Schema 中不包含 “required” 名称 - 值对,那么将不会有必填项。一个没有任何名称 - 值对的空 JSON 对象也被认为是合法的。
本章提供的例子只是简介,是冰山一角。JSON Schema 还支持正则表达式(一种字符形式,比如电子邮件地址的格式)以及枚举类型(一个包含所有可能值的列表)。
用schema校验JSON
AJV号称是最快的JSON Schema验证器,我们看一下它的官网:可以看到这个下载次数非常高,说明使用的是非常广泛的。
我们还可以看到它的性能表现,这里号称是比第二名快50%。
它的特性:它支持04,06,07的草案标准,并且支持浏览器和nodejs,可以说是比较全面的验证器了。
工具
现在我要推荐一些工具给大家。
刚刚看了schema的语法,因为schema也是JSON文件,所以写起来还是比较麻烦的,特别是你的数据稍稍复杂一点就很费时间。这里推荐一个非常方便的一个工具:JSONSchema.net。你只需要填入你的示例数据,然后这个工具就会识别并自动生成schema,当然它做不到完全准确,它只能帮你完成70%的工作,还需要你去检查和完善,不过已经可以帮我们省下很多力气了。
接下来是生成测试数据,JSON-generator可以帮你生成你想要的测试数据,它提供一些工具函数来帮助你模拟出一些你想要的数据。
接下来要介绍一个非常好用的工具:JSON-server,来看一下的官网。
它的使用非常简单,也支持很多种动作。可以做过滤,分页,简单的排序啊,数据的切片啊等等功能,对于辅助我们平常的开发什么的还是够用的,这三个工具加在一起可以帮助我们提高很多效率哈。
在JSON中进行搜索
主要是给大家推荐几个工具,它们的使用方法都非常相似哈,这里以JSONPath为例介绍一下:
- JSONPath
- JSONPointer
- jq
通过这张表我们可以看到它的查询能力还是比较全面的。
JSON与mysql
从MySQL 5.7.8 开始,MySQL支持原生的JSON格式,即有独立的json类型,用于存放 json格式的数据。
MySQL对支持JSON的做法是,在server层提供了一堆便于操作JSON的函数,至于存储,就是简单地将JSON编码成BLOB(binary large object),二进制大对象 ,然后交由存储引擎层进行处理,也就是说,MySQL 5.7的JSON支持与存储引擎没有关系,MyISAM 存储引擎也支持JSON 格式。
JSON 格式的数据并不是以string格式存储于数据库而是以内部的binary 格式,以便于快速的定位到json 格式中值
在插入和更新操作时MySQL会对JSON 类型做校验,已检查数据是否符合json格式,如果不符合则报错。
MySQL支持JSON以后,总是避免不了拿来与MongoDB进行一些比较。但是,MySQL对JSON的支持,至少有两点能够完胜MongoDB:
- 可以混合存储结构化数据和非结构化数据,同时拥有关系型数据库和非关系型数据库的优点
- 能够提供完整的事务支持
JSON与NoSQL
CouchDB
使用 JSON 文档存储数据的文档存储数据库——CouchDB。
无缝多主同步,可从大数据扩展到移动,具有直观的HTTP / JSON API,专为可靠性而设计。couchDB也可以作为一个数据库服务器来使用。
CouchDB(http://couchdb.apache.org/)是一种使用 JSON 文档存储数据的NoSQL 数据库。
Apache CouchDB是一个开源数据库,专注于易用性和成为”完全拥抱web的数据库”[1] 。它是一个使用JSON 作为存储格式,JavaScript 作为查询语言,MapReduce 和HTTP 作为API 的NoSQL 数据库。其中一个显著的功能就是多主复制。CouchDB的第一个版本发布在2005年,在2008年成为了Apache 的项目。
不同于关系型数据库 ,CouchDB没有将数据和关系存储在表格里。替代的,每个数据库是一个独立的文档集合。每一个文档维护其自己独立的数据和自包涵的schema。一个应用程序可能会访问多个数据库,比如其中一个位于用户的手机上,另一个位于在远程的服务器上。文档的元数据包含版本信息,让其能够合并可能因为数据库链接丢失导致的任何差异。
由于 CouchDB 使用文档来存储数据,因此当从数据库中查询一个账户时,得到的直接就是一个结构化的文档。没有必要进行重组。这样既高效又方便。
CouchDB 的另一个好处是有利于数据的变化。有些数据会随着时间而发生变化。当数据发生变化时,CouchDB无需修改表的结构。
MongoDB
MongoDB 是一种 NoSQL 数据库,允许开发人员以文档的形式存储数据。
MongoDB是一个文档数据库,具有您需要的可查询性和索引所需的可伸缩性和灵活性。
关于BSON(Binary JSON,BSON)
BSON 是 MongoDB 内部用于序列化 JSON 文档的一种二进制数据格式。
bson对json做了一些对存储上的优化。
json和bson的区别:
更快的遍历速度
对json格式来说,太大的json结构会导致数据遍历非常慢。在json中,要跳过一个文档进行数据读取,需要对此文档进行扫描才行,需要进行麻烦的数据结构匹配,比如括号的匹配。而bson对json的一大改进就是,它会将json的每一个元素的长度存在元素的头部,这样你只需要读取到元素长度就能直接seek到指定的点上进行读取了。
操作更简易
对json来说,数据存储是无类型的,比如你要修改基本一个值,从9到10,由于从一个字符变成了两个,所以可能其后面的所有内容都需要往后移一位才可以。 而使用bson,你可以指定这个列为数字列,那么无论数字从9长到10还是100,我们都只是在存储数字的那一位上进行修改,不会导致数据总长变大。 当然,在mongoDB中,如果数字从整形增大到长整型,还是会导致数据总长变大的。
增加了额外的数据类型
json是一个很方便的数据交换格式,但是其类型比较有限。bson在其基础上增加了“byte array”数据类型。这使得二进制的存储不再需要先base64转换后再存成json,大大减少了计算开销和数据大小。当然,在有的时候,bson相对json来说也并没有空间上的优势,比如对{“field”:7},在json的存储上7只使用了一个字节,而如果用bson,那就是至少4个字节(32位)
关于Schema
MongoDB 是没有 Schema 的,这意味着数据库既不会校验数据,也不会在存储数据时依赖Schema。然而,应用程序对存储在每个文档中的数据还是会有数据结构上的预期,因为只有这样,应用程序才能放心地使用集合与文档。
从MongoDB3.2开始,提供validator来对数据进行验证。
在创建集合的时候指定一个验证器像这样。
这个验证器也有自己的规范,这里就不一一介绍了
MessagePack
json作为数据交换格式,现在使用得越来越广泛,但是它还是有不少的弊端,MessagePack也是一个数据交换格式,它对针对JSON的一些问题做了一些优化。
图上这个json长度为27字节,但是为了表示这个数据结构,它用了9个字节(就是那些大括号、引号、冒号之类的,他们是白白多出来的)来表示那些额外添加的无意义数据。msgpack 的优化在图上展示的也比较清楚了,省去了特殊符号,用特定编码对各种类型进行定义,比如上图的A7,其中前四个bit A就是表示str的编码,而且它表示这个str的长度只用半个字节就可以表示了,也就是后面的7,因此A7的意思就是表示后面是一个7字节长度的string。
但是这个格式的可读性和可编辑性就比较差了。
核心压缩方式可参看官方说明messagepack specification
概括来讲就是:
- true、false 之类的:这些太简单了,直接给1个字节,(0xc3 表示true,0xc2表示false)
- 不用表示长度的:就是数字之类的,他们天然是定长的,是用一个字节表示后面的内容是什么,比如用(0xcc 表示这后面,是个uint 8,用oxcd表示后面是个uint 16,用 0xca 表示后面的是个float 32)。对于数字做了进一步的压缩处理,根据大小选择用更少的字节进行存储,比如一个长度<256的int,完全可以用一个字节表示。
- 不定长的:比如字符串、数组、二进制数据(bin类型),类型后面加 1~4个字节,用来存字符串的长度,如果是字符串长度是256以内的,只需要1个字节,MessagePack能存的最长的字符串,是(2^32 -1 ) 最长的4G的字符串大小。
- 高级结构:MAP结构,就是k-v 结构的数据,和数组差不多,加1~4个字节表示后面有多少个项
- Ext结构:表示特定的小单元数据。也就是用户自定义数据结构。
protocol buffer
Google Protocol Buffers 简称 Protobuf,它提供了一种灵活、高效、自动序列化结构数据的机制,可以联想 XML,但是比 XML 更小、更快、更简单。仅需要自定义一次你所需的数据格式,然后用户就可以使用 Protobuf 编译器自动生成各种语言的源码,方便的读写用户自定义的格式化的数据。与语言无关,与平台无关,还可以在不破坏原数据格式的基础上,依据老的数据格式,更新现有的数据格式。
Protobuf 的特点简单总结如下几点:
- 作用与 XML、json 类似,但它是二进制格式,性能好、效率高
- 代码生成机制,易于使用
- 解析速度快
- 支持多种语言
- 向后兼容、向前兼容
- 缺点:可读性差
目前,Protobuf 提供了两个大版本: 2.x 版本和 3.x 版本。 2.x 版本最新的版本是 2.6.1,支持 C++、Java 和 Python 三种语言的API。 3.x 版本最新的版本是 3.0.0-beta-1,支持 C++、Java、Python、Ruby、JavaNano、Objective-x 和 C# 这几种语言的 API。
- Title: 你不知道的JSON
- Author: RaHsu
- Created at : 2018-05-06 20:46:25
- Updated at : 2024-09-17 16:40:29
- Link: https://www.rahsu.com/Tech/你不知道的JSON/
- License: All Rights Reserved © RaHsu