Json_standard_definition
RFC8259:https://datatracker.ietf.org/doc/html/rfc8259
json: 简介
- json(javascript object notation)可以表示四种primitive types: strings, numbers, booleans and null, 和两种structured types:objects and arrays(这两个概念来自 JavaScript 的约定)。
- strings是由零个或多个unicode字符组成的序列。
- object是零个或多个name/value的无序集合; 其中name是strings; value是strings, numbers、booleans、null、objects或arrays。
- array是零个或多个value的有序序列。
json:语法和结构
基本语法
ws = *(
%x20 / ; Space, 空格
%x09 / ; Horizontal tab, 水平制表符, \t
%x0A / ; Line feed or New line, 换行键, \n
%x0D ; Carriage return, 回车键, \r
)
json-text = ws value ws ; value见后续解释
begin-array = ws %x5B ws ; [ left square bracket, 中括号-左
end-array = ws %x5D ws ; ] right square bracket, 中括号-右
begin-object = ws %x7B ws ; { left curly bracket, 大括号-左
end-object = ws %x7D ws ; } right curly bracket, 大括号-右
name-separator = ws %x3A ws ; : colon, 冒号
value-separator = ws %x2C ws ; , comma, 逗号
构成
所有的json-text均由value构成
value
-
value必须是object, array, string, number, 或者是下列字面意思的true, false和null之一构成。
-
虽然RFC8259并没有明确说明, 但是根据以下描述意味着json文本(也就是一个json文件的内容)只能是一个单一的json值, 这个json值可以是一个objec, array, strings, numbers, booleans and null, 但只能有一个顶级结构。
RFC 8259 的第2节明确指出:
A JSON text is a serialized value. Note that certain previous specifications of JSON constrained a JSON text to be an object or an array. Implementations that generate only objects or arrays where a JSON value is expected will be interoperable in the sense that all implementations will accept these as conforming JSON texts. However, this specification allows any JSON value.
翻译如下:
JSON 文本是一个序列化的值。请注意,以前的某些 JSON 规范将 JSON 文本限制为对象或数组。如果在需要 JSON 值的地方仅生成对象或数组的实现是可互操作的,因为所有实现都会接受这些作为符合 JSON 规范的文本。然而,这个规范允许任何 JSON 值。
-
对于json文件来说, 单个的value也是合法的, 所以以下的单个json文件都是合法的: object.json, 仅object:
{"name":"value"}
array.json, 仅array:
["value1","value2","value3"]
string.json, 仅string:
"Just a string"
number.json, 仅number:
123456
boolean.json, 仅boolean:
true
null.json, 仅null
null
语法规则如下
false = %x66.61.6c.73.65 ; false
null = %x6e.75.6c.6c ; null
true = %x74.72.75.65 ; true
value = false / null / true / object / array / number / string ; object, array, number, string见后续解释
string
- string以引号开头和结尾; 所有Unicode字符都可以放在引号内, 但必须转义的字符除外: 引号, 反斜线和控制字符(U+0000 到 U+001F)。
- 任何字符都可以被转义。如果该字符位于基本多语言平面(U+0000 到 U+FFFF)中, 则它可以表示为一个六字符序列: 一个反斜线, 后跟小写字母u, 再后跟四个编码该字符的十六进制数字。十六进制字母 A 到 F 可以是大写或小写。因此, 例如, 仅包含单个反斜线字符的字符串可以表示为”\u005C”。
- 一些流行字符的两个字符序列转义表示。因此, 例如, 仅包含单个反斜线字符的字符串可以更紧凑地表示为”\“。
- 为了转义不在基本多语言平面中的扩展字符, 该字符被表示为 12 个字符的序列, 对UTF-16代理项对进行编码。因此, 例如, 仅包含G clef (U+1D11E) 的字符串可以表示为”\uD834\uDD1E”。
语法规则如下
quotation-mark = %x22 ; "
escape = %x5C ; \ 表示转义字符
unescaped = ; 非转义字符
%x20-21 / ; 表示从空格( ,U+0020)到感叹号( !,U+0021)
%x23-5B / ; 表示从井号( #,U+0023)到左方括号( [,U+005B)
%x5D-10FFFF ; 表示从右方括号( ],U+005D)到U+10FFFF的Unicode代码点
char = unescaped / ; 未转义字符
escape ( ; 转义字符
%x22 / ; " quotation mark U+0022 用于在字符串中插入双引号
%x5C / ; \ reverse solidus U+005C 用于在字符串中插入反斜杠
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX 表示一个 Unicode 字符,其中 XXXX 是四位十六进制数,用于表示该字符的 Unicode 代码点
string = quotation-mark *char quotation-mark ;
关于字符补充内容详见标题字符补充。
number
- 数字使用十进制, 它包含一个整数, 该整数可以带有可选的减号作为前缀, 其后可以是分数部分和/或指数部分。
- 不允许使用前导零。
- 若要添加小数部分, 则小数点后跟一位或多位数字。
- 指数部分以大写或小写字母 E 开头, 后面可能跟有加号或减号。 E和可选符号后跟一位或多位数字。
- 不允许使用以下语法无法表示的数值, 例如Infinity和NaN。
- json规范允许不同的实现(即处理json的软件或库)对接受的数字的范围和精度设置限制。
- json实现通常依赖IEEE-754双精度浮点数(double precision), 如果不超出其能力范围, 不同的实现可以很好地互操作。
- 对于整数, 在
-(2^53)+1
到(2^53)-1
之间的数值是完全可互操作的,所有实现都会对这些数字的值达成一致。
语法规则如下
minus = %x2D ; - 负号
plus = %x2B ; + 正号
zero = %x30 ; 0
digit1-9 = %x31-39 ; 1-9 数字1-9的表示
decimal-point = %x2E ; . 小数点
e = %x65 / %x45 ; e/E 用来表示指数
int = zero / ( digit1-9 *DIGIT ) ; 整数部分的定义
frac = decimal-point 1*DIGIT ; 小数部分的定义
exp = e [ minus / plus ] 1*DIGIT ; 指数部分的定义
number = [ minus ] int [ frac ] [ exp ] ; 数值的总体定义
array
- 没有要求数组中的值必须相同类型
语法规则如下
begin-array = ws %x5B ws ; [ left square bracket
value-separator = ws %x2C ws ; , comma
end-array = ws %x5D ws ; ] right square bracket
array = begin-array [ value *( value-separator value ) ] end-array
object
- object中的name应该是唯一的, 虽然这是推荐的最佳实践, 但并不是强制要求。如果json object中的所有name都是唯一的, 那么不同的软件实现之间在处理该object时能够达成一致, 确保互操作性, 这意味着接收该对象的所有软件都能正确识别每个键对应的值。如果对象中存在重复的name, 那么不同软件的处理方式可能会不同, 导致行为不可预测。例如: 有的软件只会返回最后一个name/value; 有的软件会报告错误或无法解析这个对象; 也有的软件会返回所有的键值对, 包括重复的键名。
- 如果一个实现不依赖对象成员的顺序(最佳实践), 那么它在不同的实现之间就能够保持互操作性, 也就是说它不会受到这些顺序差异的影响。但是实现仍然可以保持对象中键值对的顺序。
语法规则如下
begin-object = ws %x7B ws ; { left curly bracket
name-separator = ws %x3A ws ; : colon
end-object = ws %x7D ws ; } right curly bracket
member = string name-separator value
object = begin-object [ member *( value-separator member ) ] end-object
字符补充
-
开放的系统之间交换 JSON 文本时, 必须使用 UTF-8 编码, 保证不同系统之间的数据兼容性。
-
禁止添加 BOM(Byte Order Mark): 在网络传输的json文本开头, 不允许添加字节顺序标记(BOM)。BOM 是一种用于指示文本文件的字节顺序的标记, 但json规范要求在传输json文本时不能使用BOM。
- 在Unicode编码中, BOM是一个可选的字符, 用于表示文本的字节顺序和编码格式。
- 对于UTF-16和UTF-32编码, BOM可以指示字节序(大端序或小端序)。
- 对于UTF-8编码, BOM 并不影响字节序, 因为 UTF-8 是字节顺序无关的编码。
-
忽略 BOM: 为了确保互操作性, 解析 JSON 文本的实现可以选择忽略 BOM 的存在, 而不是将其视为错误。
-
当json中的字符串完全由有效的Unicode字符组成时, 不同的解析器可以一致地解释这些字符串。
-
如果json中包含无法有效表示的字符(如未配对的 UTF-16 代理项), 处理这些字符的软件可能会表现出不可预测的行为, 甚至可能导致运行时错误。
-
软件实现需要确保字符串比较的一致性。如果将字符串的文本表示转换为Unicode代码单元进行比较, 所有实现将一致地判断字符串的相等性。例如,
a\\b
和a\u005Cb
, 实际上,这两个表示的字符串是相同的(a\b
) -
避免将转义字符与原始字符形式混淆, 以确保比较操作的正确性。
解析器和生成器
- 解析器的定义:JSON 解析器将 JSON 文本转换为另一种表示形式。解析器必须能够接受所有符合 JSON 语法的文本。这意味着解析器必须正确处理所有符合 JSON 规范的输入。解析器可以限制接受的文本的大小、限制 JSON 对象和数组的最大嵌套深度、限制接受的数字的范围和精度、限制字符串的最大长度以及字符串中允许的字符类型
- 扩展性:解析器可以接受非标准的 JSON 格式或扩展。这允许解析器支持 JSON 规范之外的额外特性,但这不是必须的,也不应影响标准 JSON 的处理。
- 生成器的定义:JSON 生成器生成 JSON 文本。生成的文本必须严格符合 JSON 语法规范。这意味着生成器生成的 JSON 数据必须是有效的 JSON 格式,并符合 JSON 规范的所有要求。
json sample
这是一个json object
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"Animated" : false,
"IDs": [116, 943, 234, 38793]
}
}
这是一个json array并且包含了两个元素object
[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]
下列是三个只有value的json文本
第一个
"Hello world!"
第二个
42
第三个
true