JSON 對象

2018-06-16 15:49 更新

JSON 對象是一個單一的對象,它包含兩個函數(shù),parse 和 stringify,是用于解析和構(gòu)造 JSON 文本的。JSON 數(shù)據(jù)的交換格式在 RFC4627 里進行了描述。 <http://www.ietf.org/rfc/rfc4627.txt>。本規(guī)范里面的 JSON 交換格式會使用 RFC4627 里所描述的,以下兩點除外:

  • ECMAScript JSON 文法中的頂級 JSONText 產(chǎn)生式是由 JSONValue 構(gòu)成,而不是 RFC4627 中限制成的 JSONObject 或者 JSONArray。
  • 確認 JSON.parse 和 JSON.stringify 的實現(xiàn),它們必須準確的支持本規(guī)范描述的交換格式,而不允許對格式進行刪除或擴展。這一點要區(qū)別于 RFC4627,它允許 JSON 解析器接受 non-JSON 的格式和擴展。

 JSON 對象內(nèi)部屬性 [[Prototype]] 的值是標準內(nèi)建的 Object 原型對象(15.2.4)。內(nèi)部屬性 [[Class]] 的值是“JSON”。內(nèi)部屬性 [[Extensible]] 的值設(shè)置為 true。

 JSON 對象沒有內(nèi)部屬性 [[Construct]];不能把 JSON 對象當作構(gòu)造器來使用 new 操作符。

 JSON 對象沒有內(nèi)部屬性 [[Call]]; 不能把 JSON 對象當作函數(shù)來調(diào)用。

JSON 語法

 JSON.stringify 會產(chǎn)生一個符合 JSON 語法的字符串。JSON.parse 接受的是一個符合 JSON 語法的字符串。

JSON 詞法

 類似于 ECMAScript 源文本,JSON 是由一系列符合 SourceCharacter 規(guī)則的字符構(gòu)成的。JSON 詞法定義的 tokens 使得 JSON 文本類似于 ECMAScript 詞法定義的 tokens 得到的 ECMAScript 源文本。JSON 詞法僅能識別由 JSONWhiteSpace 產(chǎn)生式得到的空白字符。在語法上,所有非終止符均不是由“JSON”字符開始,而是由 ECMAScript 詞法產(chǎn)生式定義的。

 語法

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 語法

 根據(jù) 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函數(shù)解析一段JSON文本(JSON格式字符串),生成一個ECMAScript值。JSON格式是ECMAScript直接量 的受限模式。JSON對象可以被理解為ECMAScript對象。JSON數(shù)組可以被理解為ECMAScript數(shù)組。JSON字符串、數(shù)字、布爾值以及null可以被認為是ECMAScript字符串、數(shù)字、布爾值以及null。JSON使用受限更多的空白字符集合,并且允許Unicode碼點U+2028和U+2029直接出現(xiàn)在JSONString直接量當中而無需使用轉(zhuǎn)義序列。解析流程與11.1.4和11.1.5一樣,但是由JSON語法限定。

 可選參數(shù)reviver是一個接受兩個參數(shù)的函數(shù)(key和value)。它可以過濾和轉(zhuǎn)換結(jié)果。它在每個key/value對產(chǎn)生時被調(diào)用,它的返回值可以用于替代原本的值。如果它原樣返回接收到的,那么結(jié)構(gòu)不會被改變。如果它返回undefined,那么屬性會被從結(jié)果中刪除。

  1. 令JText為ToString(text)
  2. 以15.12.1所述語法解析JText。如果JText不能以JSON grammar解析成JSONText,則拋出SyntaxError異常。
  3. 令unfiltered為按ECMAScript程序(但是用JSONString替換StringLiteral)解析和執(zhí)行JText的結(jié)果。注因JText符合JSON語法,這個結(jié)果要么是原始值類型要么是ArrayLiteral或者ObjectLiteral所定義的對象。
  4. 若IsCallable(reviver)為true則令root為由表達式new Object()創(chuàng)建的新對象,其中Object是以O(shè)bject為名的標準內(nèi)置的構(gòu)造器。以空字符串和屬性描述{Value: unfiltered, Writable: true, Enumerable: true, Configurable: true}以及false為參數(shù)調(diào)用root的DefineOwnProperty內(nèi)置方法。返回傳入root和空字符串為參數(shù)調(diào)用抽象操作Walk的結(jié)果,抽象操作Walk如下文所定義。
  5. 否則,返回unfiltered。

 抽象操作Walk是一個遞歸的抽象操作,它接受兩個參數(shù):一個持有對象和表示一個該對象的屬性名的String。Walk使用最開始被傳入parse函數(shù)的reviver的值。

  1. 令val為以參數(shù)name調(diào)用hold的get內(nèi)部方法的結(jié)果。
  2. 若val為對象,則若val的Class內(nèi)部屬性為"Array"設(shè)I為0令len為以參數(shù)"length"調(diào)用val的get內(nèi)部方法的結(jié)果當I<len時重復令newElement為調(diào)用抽象操作Walk的結(jié)果,傳入val和ToString(I)為參數(shù)。若newElement為undefined,則以ToString(I)和false做參數(shù),調(diào)用val的內(nèi)部方法Delete否則,以ToString(I),屬性描述{Value: newElement, Writable: true, Enumerable: true, Configurable: true}以及false做參數(shù)調(diào)用調(diào)用val的內(nèi)部方法DefineOwnProperty對I加1否則令keys為包含val所有的具有Enumerable特性的屬性名String值的內(nèi)部類型List。字符串的順序應(yīng)當與內(nèi)置函數(shù)Object.keys一致。對于keys中的每個字符串P做一下令newElement為調(diào)用抽象操作Walk的結(jié)果,傳入val和P為參數(shù)。若newElement為undefined,則以P和false做參數(shù),調(diào)用val的內(nèi)部方法Delete否則,以P,屬性描述{Value: newElement, Writable: true, Enumerable: true, Configurable: true}以及false做參數(shù)調(diào)用調(diào)用val的內(nèi)部方法DefineOwnProperty
  3. 返回傳入holder作為this值以及以name和val構(gòu)成的參數(shù)列表調(diào)用reviver的Call內(nèi)部屬性的結(jié)果。

 實現(xiàn)不允許更改JSON.parse的實現(xiàn)以擴展JSON語法。如果一個實現(xiàn)想要支持更改或者擴展過的JSON交換格式它必須以定義一個不同的parse函數(shù)的方式做這件事。

 在對象中存在同名字符串的情況下,同一key的值會被按照文本順序覆蓋掉。

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

 stringify函數(shù)返回一個JSON格式的字符串,用以表示一個ECMAScript值。它可以接受三個參數(shù)。第一個參數(shù)是必選的。value參數(shù)是一個ECMAScript值,它通常是對象或者數(shù)組,盡管它也可以是String, Boolean, Number 或者是 null。可選的replacer參數(shù)要么是個可以修改對象和數(shù)組字符串化的方式的函數(shù),要么是個扮演選擇對象字符串化的屬性的白名單這樣的角色的String和Number組成的數(shù)組??蛇x的space參數(shù)是一個String或者Number,可以允許結(jié)果中插入空白符以改善人類可讀性。

 以下為字符串化一對象的步驟:

  1. 令stack為空List
  2. 令indent為空String
  3. 令PropertyList和ReplacerFunction為undefined
  4. 若Type(replacer)為Object,則若IsCallable(replacer)為true,則令ReplacerFunction為replacer否則若replacer的內(nèi)部屬性Class為"Array",則令PropertyList為一空內(nèi)部類型List對于所有名是數(shù)組下標的replacer的屬性v.以數(shù)組下標遞增順序枚舉屬性令item為undefined若Type(v)為String則 令item為v.否則若Type(v)為Number則 令item為ToString(v).否則若Type(v)為Object則,若v的Class內(nèi)部屬性為"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內(nèi)部屬性為"Number"則,令space為ToNumber(space)否則若space的Class內(nèi)部屬性為"String"則,令space為ToString(space)
  6. 若Type(space)為Number 令space為min(10, ToInteger(space)) 設(shè)gap為一包含space個空格的String. 這將會是空String加入space小于1.
  7. 否則若Type(space)為String若space中字符個數(shù)為10或者更小, 設(shè)gap為space,否則設(shè)gap為包含前10個space中字符的字符串
  8. 否則 設(shè)gap為空String.
  9. 令wrapper為一個如同以表達式new Object()創(chuàng)建的新對象,其中Object是這個名字的標準內(nèi)置構(gòu)造器。
  10. 以參數(shù)空String, 屬性描述{Value: value, Writable: true, Enumerable: true, Configurable: true}, 和false調(diào)用wrapper的DefineOwnProperty內(nèi)部方法。
  11. 返回以空String和wrapper調(diào)用抽象方法Str的結(jié)果。

 抽象操作Str(key, holder)可以訪問調(diào)用它的stringify方法中的ReplacerFunction。其算法如下:

  1. 令value為以key為參數(shù)調(diào)用holder的內(nèi)部方法Get
  2. 若Type(value)為Object,則令toJSON為以"toJSON"為參數(shù)調(diào)用value的內(nèi)部方法GetIf IsCallable(toJSON) is true令value為以調(diào)用toJSON的內(nèi)部方法Call的結(jié)果,傳入value為this值以及由key構(gòu)成的參數(shù)列表
  3. 若ReplacerFunction為not undefined,則令value為以調(diào)用ReplacerFunction的內(nèi)部方法Call的結(jié)果,傳入holder為this值以及由key and value構(gòu)成的參數(shù)列表
  4. 若Type(value)為Object則,若value的Class內(nèi)部屬性為"Number"則,令value為ToNumber(value)否則若value的Class內(nèi)部屬性為"String"則,令value為ToString(value)否則若value的Class內(nèi)部屬性為"Boolean"則,令value為value的value of the PrimitiveValue內(nèi)部屬性
  5. 若value為null則 返回 "null".
  6. 若value為true則 返回 "true".
  7. 若value為false則 返回 "false".
  8. 若Type(value)為String,則返回以value調(diào)用Quote抽象操作的結(jié)果。
  9. 若Type(value)為Number若value為finite則 返回 ToString(value).否則, 返回"null".
  10. 若Type(value)為Object,且IsCallable(value)為false若value的Class內(nèi)部屬性為"Array"則返回以value為參數(shù)調(diào)用抽象操作JA的結(jié)果否則, 返回以value.為參數(shù)調(diào)用抽象操作value的結(jié)果
  11. 返回undefined.

 抽象操作Quote(value)將一個String值封裝在雙引號中,并且對其中的字符轉(zhuǎn)義。

  1. 令product為雙引號字符
  2. 對value中的每一個字符C若C為雙引號字符或者反斜杠字符令product為product和反斜杠連接的結(jié)果令product為product與C的連接否則若C為退格,formfeed換行回車揮著tab令product為product與反斜杠字符的連接令abbrev為如下表所示C對應(yīng)的字符: backspace "b" formfeed "f" newline "n" carriage return "r" tab "t"令product為product與abbrev的連接否則若C為代碼值小于space的控制字符令product為product與反斜杠字符的連接令product為product與"u"的連接令hex為轉(zhuǎn)換C代碼值按十六進制轉(zhuǎn)換到四位字符串的結(jié)果令product為product與hex的連接否則令product為product與C的連接
  3. 令product為product與雙引號字符的連接
  4. 返回 product.

 抽象操作JO(value)序列化一個對象,它可以訪問調(diào)用它的方法中的stack, indent, gap, PropertyList,ReplacerFunction以及space

  1. 若stack包含value,則拋出一個TypeError,因為對象結(jié)構(gòu)中存在循環(huán)。
  2. 將value添加到stack.
  3. 令stepback為indent
  4. 令indent為indent與gap的連接
  5. 若PropertyList沒有被定義,則令K為PropertyList
  6. 否則令K為以由所有Enumerable特性為true的自身屬性名構(gòu)成的內(nèi)部String列表類型.
  7. 令partial為空List
  8. 對于K的每一個元素P令strP為以P和value為參數(shù)調(diào)用抽象操作Str的結(jié)果若strP沒有被定義令member為以P為參數(shù)調(diào)用抽象操作P的結(jié)果令member為member與冒號字符的連接若gap不為空String令member為member與空格字符的連接令member為member與strP的連接將member添加到partial.
  9. 若partial為empty,則令final為"{}"
  10. 否則若gap為空String令properties為一個連接所有partial中的字符串而成的字符串,鍵值對之間用逗號分隔。第一個字符串之前和最后一個字符串之后沒有逗號。令final為連接 "{", properties, 和"}"的結(jié)果否則 gap 不是空String令separator為連接 逗號字符,換行字符以及indent而成的字符串。令properties為一個連接所有partial中的字符串而成的字符串,鍵值對之間用separator分隔。第一個字符串之前和最后一個字符串之后沒有separator。令final為連接"{", 換行符, indent, properties, 換行符, stepback, 和"}"的結(jié)果。
  11. 移除stack中的最后一個元素。
  12. 令indent為stepback
  13. 返回final.

 抽象操作JA(value)序列化一個數(shù)組。它可以訪問調(diào)用它的stringify方法中的stack, indent, gap, PropertyList,ReplacerFunction以及space。數(shù)組的表示中僅包擴零到array.length-1的區(qū)間。命名的屬性將會被從字符串化操作中排除。數(shù)組字符串化成開頭的左方括號,逗號分隔的元素,以及結(jié)束的右方括號。

  1. 若stack包含value,則拋出一個TypeError,因為對象結(jié)構(gòu)中存在循環(huán)。
  2. 將value添加到stack.
  3. 令stepback為indent
  4. 令indent為indent與gap的連接
  5. 令partial為空List
  6. 令len為以"length"為參數(shù)調(diào)用value的內(nèi)部方法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, 和"]"的結(jié)果否則令separator為逗號字符,換行字符以及indent而成的字符串。令properties為一個連接所有partial中的字符串而成的字符串,鍵值對之間用separator分隔。第一個字符串之前和最后一個字符串之后沒有separator。令final為連接"[", 換行符, indent, properties, 換行符, stepback, 和"]"的結(jié)果。
  11. 移除stack中的最后一個元素。
  12. 令indent為stepback
  13. 返回final.

 JSON結(jié)構(gòu)允許任何深度的嵌套,但是不能夠循環(huán)引用。若value是或者包含了一個循環(huán)結(jié)構(gòu),則stringify函數(shù)必須拋出一個TypeError異常。以下是一個不能夠被字符串化的值的例子:

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

 符號式簡單值按以下方式表示:

  1. null值在JSON文本中表示為字符串null
  2. undefined 值不出現(xiàn)
  3. true值在JSON文本中表示為字符串true
  4. false值在JSON文本中表示為字符串false

 字符串值用雙引號括起。字符"和\會被轉(zhuǎn)義成帶\前綴的??刂谱址棉D(zhuǎn)義序列\(zhòng)uHHHH替換,或者使用簡略形式 \b(backspace), \f (formfeed), \n (newline), \r (carriage return), \t (tab)

 有窮的數(shù)字按照調(diào)用ToString(number)字符串化。NaN和不論正負的Infinity都表示為字符串null

 沒有JSON表示的值(如undefined和函數(shù))不會產(chǎn)生字符串。而是會產(chǎn)生undefined值。在數(shù)組中這些值表示為字符串null。在對象中不能表示的值會導致屬性被排除在字符串化過程之外。

 對象表示為開頭的左大括號跟著零個或者多個屬性,以逗號分隔,以右大括號結(jié)束。屬性是用用來表示key或者屬性名的引號引起的字符串,冒號然后是字符串化的屬性值。數(shù)組表示為開頭的左方括號,后跟零個或者多個值,以逗號分隔,以右方括號結(jié)束。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號