JSON 对象

2018-06-16 15:49 更新

JSON 对象是一个单一的对象,它包含两个函数,parse 和 stringify,是用于解析和构造 JSON 文本的。JSON 数据的交换格式在 RFC4627 里进行了描述。 <http://www.ietf.org/rfc/rfc4627.txt>。本规范里面的 JSON 交换格式会使用 RFC4627 里所描述的,以下两点除外:

  • ECMAScript JSON 文法中的顶级 JSONText 产生式是由 JSONValue 构成,而不是 RFC4627 中限制成的 JSONObject 或者 JSONArray。
  • 确认 JSON.parse 和 JSON.stringify 的实现,它们必须准确的支持本规范描述的交换格式,而不允许对格式进行删除或扩展。这一点要区别于 RFC4627,它允许 JSON 解析器接受 non-JSON 的格式和扩展。

 JSON 对象内部属性 [[Prototype]] 的值是标准内建的 Object 原型对象(15.2.4)。内部属性 [[Class]] 的值是“JSON”。内部属性 [[Extensible]] 的值设置为 true。

 JSON 对象没有内部属性 [[Construct]];不能把 JSON 对象当作构造器来使用 new 操作符。

 JSON 对象没有内部属性 [[Call]]; 不能把 JSON 对象当作函数来调用。

JSON 语法

 JSON.stringify 会产生一个符合 JSON 语法的字符串。JSON.parse 接受的是一个符合 JSON 语法的字符串。

JSON 词法

 类似于 ECMAScript 源文本,JSON 是由一系列符合 SourceCharacter 规则的字符构成的。JSON 词法定义的 tokens 使得 JSON 文本类似于 ECMAScript 词法定义的 tokens 得到的 ECMAScript 源文本。JSON 词法仅能识别由 JSONWhiteSpace 产生式得到的空白字符。在语法上,所有非终止符均不是由“JSON”字符开始,而是由 ECMAScript 词法产生式定义的。

 语法

JSONWhiteSpace :: <tab> <cr> <lf> <sp> JSONString :: " JSONStringCharactersopt " JSONStringCharacters :: JSONStringCharacter JSONStringCharactersopt JSONStringCharacter :: SourceCharacter 但非 双引号 " 或反斜杠 \ 或 U+0000 抑或是 U+001F \ JSONEscapeSequenceJSONEscapeSequence :: JSONEscapeCharacter UnicodeEscapeSequence JSONEscapeCharacter :: 以下之一 " / \ b f n r t JSONNumber :: -optDecimalIntegerLiteral JSONFractionopt ExponentPartopt JSONFraction :: . DecimalDigits JSONNullLiteral :: NullLiteral JSONBooleanLiteral :: BooleanLiteral

JSON 语法

 根据 JSON 词法定义的 tokens,JSON 语法定义了一个合法的 JSON 文本。语法的目标符号是 JSONText。

 语法

JSONText : JSONValue JSONValue : JSONNullLiteral JSONBooleanLiteral JSONObject JSONArray JSONString JSONNumberJSONObject : { } { JSONMemberList } JSONMember : JSONString : JSONValue JSONMemberList : JSONMember JSONMemberList , JSONMemberJSONArray : [ ] [ JSONElementList ]JSONElementList : JSONValue JSONElementList , JSONValue

parse ( text [ , reviver ] )

 parse函数解析一段JSON文本(JSON格式字符串),生成一个ECMAScript值。JSON格式是ECMAScript直接量 的受限模式。JSON对象可以被理解为ECMAScript对象。JSON数组可以被理解为ECMAScript数组。JSON字符串、数字、布尔值以及null可以被认为是ECMAScript字符串、数字、布尔值以及null。JSON使用受限更多的空白字符集合,并且允许Unicode码点U+2028和U+2029直接出现在JSONString直接量当中而无需使用转义序列。解析流程与11.1.4和11.1.5一样,但是由JSON语法限定。

 可选参数reviver是一个接受两个参数的函数(key和value)。它可以过滤和转换结果。它在每个key/value对产生时被调用,它的返回值可以用于替代原本的值。如果它原样返回接收到的,那么结构不会被改变。如果它返回undefined,那么属性会被从结果中删除。

  1. 令JText为ToString(text)
  2. 以15.12.1所述语法解析JText。如果JText不能以JSON grammar解析成JSONText,则抛出SyntaxError异常。
  3. 令unfiltered为按ECMAScript程序(但是用JSONString替换StringLiteral)解析和执行JText的结果。注因JText符合JSON语法,这个结果要么是原始值类型要么是ArrayLiteral或者ObjectLiteral所定义的对象。
  4. 若IsCallable(reviver)为true则令root为由表达式new Object()创建的新对象,其中Object是以Object为名的标准内置的构造器。以空字符串和属性描述{Value: unfiltered, Writable: true, Enumerable: true, Configurable: true}以及false为参数调用root的DefineOwnProperty内置方法。返回传入root和空字符串为参数调用抽象操作Walk的结果,抽象操作Walk如下文所定义。
  5. 否则,返回unfiltered。

 抽象操作Walk是一个递归的抽象操作,它接受两个参数:一个持有对象和表示一个该对象的属性名的String。Walk使用最开始被传入parse函数的reviver的值。

  1. 令val为以参数name调用hold的get内部方法的结果。
  2. 若val为对象,则若val的Class内部属性为"Array"设I为0令len为以参数"length"调用val的get内部方法的结果当I<len时重复令newElement为调用抽象操作Walk的结果,传入val和ToString(I)为参数。若newElement为undefined,则以ToString(I)和false做参数,调用val的内部方法Delete否则,以ToString(I),属性描述{Value: newElement, Writable: true, Enumerable: true, Configurable: true}以及false做参数调用调用val的内部方法DefineOwnProperty对I加1否则令keys为包含val所有的具有Enumerable特性的属性名String值的内部类型List。字符串的顺序应当与内置函数Object.keys一致。对于keys中的每个字符串P做一下令newElement为调用抽象操作Walk的结果,传入val和P为参数。若newElement为undefined,则以P和false做参数,调用val的内部方法Delete否则,以P,属性描述{Value: newElement, Writable: true, Enumerable: true, Configurable: true}以及false做参数调用调用val的内部方法DefineOwnProperty
  3. 返回传入holder作为this值以及以name和val构成的参数列表调用reviver的Call内部属性的结果。

 实现不允许更改JSON.parse的实现以扩展JSON语法。如果一个实现想要支持更改或者扩展过的JSON交换格式它必须以定义一个不同的parse函数的方式做这件事。

 在对象中存在同名字符串的情况下,同一key的值会被按照文本顺序覆盖掉。

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

 stringify函数返回一个JSON格式的字符串,用以表示一个ECMAScript值。它可以接受三个参数。第一个参数是必选的。value参数是一个ECMAScript值,它通常是对象或者数组,尽管它也可以是String, Boolean, Number 或者是 null。可选的replacer参数要么是个可以修改对象和数组字符串化的方式的函数,要么是个扮演选择对象字符串化的属性的白名单这样的角色的String和Number组成的数组。可选的space参数是一个String或者Number,可以允许结果中插入空白符以改善人类可读性。

 以下为字符串化一对象的步骤:

  1. 令stack为空List
  2. 令indent为空String
  3. 令PropertyList和ReplacerFunction为undefined
  4. 若Type(replacer)为Object,则若IsCallable(replacer)为true,则令ReplacerFunction为replacer否则若replacer的内部属性Class为"Array",则令PropertyList为一空内部类型List对于所有名是数组下标的replacer的属性v.以数组下标递增顺序枚举属性令item为undefined若Type(v)为String则 令item为v.否则若Type(v)为Number则 令item为ToString(v).否则若Type(v)为Object则,若v的Class内部属性为"String" or "Number"则 令item为ToString(v).若item is not undefined and item为not currently an element of PropertyList则,Append item to the end of PropertyList.
  5. 若Type(space)为Object则,若space的Class内部属性为"Number"则,令space为ToNumber(space)否则若space的Class内部属性为"String"则,令space为ToString(space)
  6. 若Type(space)为Number 令space为min(10, ToInteger(space)) 设gap为一包含space个空格的String. 这将会是空String加入space小于1.
  7. 否则若Type(space)为String若space中字符个数为10或者更小, 设gap为space,否则设gap为包含前10个space中字符的字符串
  8. 否则 设gap为空String.
  9. 令wrapper为一个如同以表达式new Object()创建的新对象,其中Object是这个名字的标准内置构造器。
  10. 以参数空String, 属性描述{Value: value, Writable: true, Enumerable: true, Configurable: true}, 和false调用wrapper的DefineOwnProperty内部方法。
  11. 返回以空String和wrapper调用抽象方法Str的结果。

 抽象操作Str(key, holder)可以访问调用它的stringify方法中的ReplacerFunction。其算法如下:

  1. 令value为以key为参数调用holder的内部方法Get
  2. 若Type(value)为Object,则令toJSON为以"toJSON"为参数调用value的内部方法GetIf IsCallable(toJSON) is true令value为以调用toJSON的内部方法Call的结果,传入value为this值以及由key构成的参数列表
  3. 若ReplacerFunction为not undefined,则令value为以调用ReplacerFunction的内部方法Call的结果,传入holder为this值以及由key and value构成的参数列表
  4. 若Type(value)为Object则,若value的Class内部属性为"Number"则,令value为ToNumber(value)否则若value的Class内部属性为"String"则,令value为ToString(value)否则若value的Class内部属性为"Boolean"则,令value为value的value of the PrimitiveValue内部属性
  5. 若value为null则 返回 "null".
  6. 若value为true则 返回 "true".
  7. 若value为false则 返回 "false".
  8. 若Type(value)为String,则返回以value调用Quote抽象操作的结果。
  9. 若Type(value)为Number若value为finite则 返回 ToString(value).否则, 返回"null".
  10. 若Type(value)为Object,且IsCallable(value)为false若value的Class内部属性为"Array"则返回以value为参数调用抽象操作JA的结果否则, 返回以value.为参数调用抽象操作value的结果
  11. 返回undefined.

 抽象操作Quote(value)将一个String值封装在双引号中,并且对其中的字符转义。

  1. 令product为双引号字符
  2. 对value中的每一个字符C若C为双引号字符或者反斜杠字符令product为product和反斜杠连接的结果令product为product与C的连接否则若C为退格,formfeed换行回车挥着tab令product为product与反斜杠字符的连接令abbrev为如下表所示C对应的字符: backspace "b" formfeed "f" newline "n" carriage return "r" tab "t"令product为product与abbrev的连接否则若C为代码值小于space的控制字符令product为product与反斜杠字符的连接令product为product与"u"的连接令hex为转换C代码值按十六进制转换到四位字符串的结果令product为product与hex的连接否则令product为product与C的连接
  3. 令product为product与双引号字符的连接
  4. 返回 product.

 抽象操作JO(value)序列化一个对象,它可以访问调用它的方法中的stack, indent, gap, PropertyList,ReplacerFunction以及space

  1. 若stack包含value,则抛出一个TypeError,因为对象结构中存在循环。
  2. 将value添加到stack.
  3. 令stepback为indent
  4. 令indent为indent与gap的连接
  5. 若PropertyList没有被定义,则令K为PropertyList
  6. 否则令K为以由所有Enumerable特性为true的自身属性名构成的内部String列表类型.
  7. 令partial为空List
  8. 对于K的每一个元素P令strP为以P和value为参数调用抽象操作Str的结果若strP没有被定义令member为以P为参数调用抽象操作P的结果令member为member与冒号字符的连接若gap不为空String令member为member与空格字符的连接令member为member与strP的连接将member添加到partial.
  9. 若partial为empty,则令final为"{}"
  10. 否则若gap为空String令properties为一个连接所有partial中的字符串而成的字符串,键值对之间用逗号分隔。第一个字符串之前和最后一个字符串之后没有逗号。令final为连接 "{", properties, 和"}"的结果否则 gap 不是空String令separator为连接 逗号字符,换行字符以及indent而成的字符串。令properties为一个连接所有partial中的字符串而成的字符串,键值对之间用separator分隔。第一个字符串之前和最后一个字符串之后没有separator。令final为连接"{", 换行符, indent, properties, 换行符, stepback, 和"}"的结果。
  11. 移除stack中的最后一个元素。
  12. 令indent为stepback
  13. 返回final.

 抽象操作JA(value)序列化一个数组。它可以访问调用它的stringify方法中的stack, indent, gap, PropertyList,ReplacerFunction以及space。数组的表示中仅包扩零到array.length-1的区间。命名的属性将会被从字符串化操作中排除。数组字符串化成开头的左方括号,逗号分隔的元素,以及结束的右方括号。

  1. 若stack包含value,则抛出一个TypeError,因为对象结构中存在循环。
  2. 将value添加到stack.
  3. 令stepback为indent
  4. 令indent为indent与gap的连接
  5. 令partial为空List
  6. 令len为以"length"为参数调用value的内部方法Get
  7. 令index为0
  8. 当index < len时重复以下令strP为the result of calling the abstract operation Str with arguments ToString(index) and value若strP没有被定义添加null到 partial.否则添加strP到 partial.使index增加1.
  9. 若partial为空,则令final为"[]"
  10. 否则若gap为空String令properties为为一个连接所有partial中的字符串而成的字符串,键值对之间用逗号分隔。第一个字符串之前和最后一个字符串之后没有逗号。令final为连接 "[", properties, 和"]"的结果否则令separator为逗号字符,换行字符以及indent而成的字符串。令properties为一个连接所有partial中的字符串而成的字符串,键值对之间用separator分隔。第一个字符串之前和最后一个字符串之后没有separator。令final为连接"[", 换行符, indent, properties, 换行符, stepback, 和"]"的结果。
  11. 移除stack中的最后一个元素。
  12. 令indent为stepback
  13. 返回final.

 JSON结构允许任何深度的嵌套,但是不能够循环引用。若value是或者包含了一个循环结构,则stringify函数必须抛出一个TypeError异常。以下是一个不能够被字符串化的值的例子:

a = []; a[0] = a; my_text = JSON.stringify(a); // This must throw an TypeError.

 符号式简单值按以下方式表示:

  1. null值在JSON文本中表示为字符串null
  2. undefined 值不出现
  3. true值在JSON文本中表示为字符串true
  4. false值在JSON文本中表示为字符串false

 字符串值用双引号括起。字符"和\会被转义成带\前缀的。控制字符用转义序列\uHHHH替换,或者使用简略形式 \b(backspace), \f (formfeed), \n (newline), \r (carriage return), \t (tab)

 有穷的数字按照调用ToString(number)字符串化。NaN和不论正负的Infinity都表示为字符串null

 没有JSON表示的值(如undefined和函数)不会产生字符串。而是会产生undefined值。在数组中这些值表示为字符串null。在对象中不能表示的值会导致属性被排除在字符串化过程之外。

 对象表示为开头的左大括号跟着零个或者多个属性,以逗号分隔,以右大括号结束。属性是用用来表示key或者属性名的引号引起的字符串,冒号然后是字符串化的属性值。数组表示为开头的左方括号,后跟零个或者多个值,以逗号分隔,以右方括号结束。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号