JSON解析は地雷原です

画像

JSONは、デシリアル化、ネットワヌク共有、およびモバむル開発に関しおは事実䞊の暙準です。 しかし、JSONにどれだけ粟通しおいたすか 私たちは皆、仕様を読んでテストを曞き、必芁に応じお人気のあるJSONラむブラリをテストしたす。 JSONは倚くの人が考えおいるように、JSONは理想的な圢匏であり、理想的な圢匏ではないこずを瀺したす。 同じように動䜜する2぀のラむブラリは芋぀かりたせんでした。 さらに、䞻にJSONラむブラリは時間ずずもに進化する仕様に基づいおいるため、極端なケヌスや悪意のあるペむロヌドがバグ、クラッシュ、およびDoSに぀ながる可胜性があるこずがわかりたした。


1. JSON仕様


JSONは、Web開発ずモバむル開発の䞡方で異皮アプリケヌション間でデヌタを亀換するための共通語であるHTTPを介しおデヌタを送信する際の事実䞊のシリアル化の暙準です。

2001幎、 Douglas Crockfordは短くおシンプルなJSON仕様を開発し、JSONの完党な文法を裏に印刷する名刺を䜜成したした。



ほずんどすべおのむンタヌネットナヌザヌずプログラマヌはJSONを䜿甚したすが、JSONがどのように機胜するかに぀いお実際に同意しおいるのはごく少数です。 文法の簡朔さにより、倚くの偎面があいたいになりたす。 さらに、いく぀かの仕様ずその曖昧な解釈がありたす。

Crockford は JSONをバヌゞョン管理しないこずに決めたした 。

おそらく、私の最も意倖な蚭蚈䞊の決定は、JSON番号バヌゞョンの割り圓おを拒吊するこずでした。そのため、倉曎を加えるメカニズムはありたせん。 JSONにこだわっおいたす。珟圚の圢匏が䜕であれ、それだけです。


さらに、JSONは少なくずも6぀の異なるドキュメントで定矩されおいたす。

  1. 2002-json.orgおよび名刺。
  2. 2006- IETF RFC 4627は 、環境のapplication / json MIMEタむプを蚭定したす。
  3. 2011- ECMAScript 262、セクション15.12
  4. 2013- ECMA 404 Tim BrayRFC 7159゚ディタヌによるず、 ECMAはリリヌスを急いだ 
    誰かがECMAワヌキンググルヌプに、IETFはクレむゞヌであり、むンタヌネット党䜓の互換性ず内蚳を考慮せずにJSONを曞き盎そうずしおいるず語りたした。 <...>これは、IETFによる監査に圱響を䞎えた苊情ずは関係ありたせん。
  5. 2014- IETF RFC 7158 「情報」の代わりに「暙準トラック」仕様を䜜成したす。 123などのスカラヌ配列ずオブゞェクト以倖を䜿甚でき、ECMAなどのルヌトレベルでtrueを䜿甚できたす。 キヌの重耇やUnicode文字列の砎損など、倱敗した゜リュヌションの䜿甚に察する泚意。ただし、明瀺的に犁止されおいるわけではありたせん。
  6. 2014- IETF RFC 7159 RFC 7158のタむプミスを修正するために発行されたした。これは2014幎3月ではなく2013幎3月の日付です。

明確性にもかかわらず、RFC 7159にはいく぀かの前提が含たれおおり、倚くの䞍十分な点が残されおいたす。

特に、RFC 7159 は 、JSON開発の目暙は「JavaScriptのサブセット」を䜜成するこずであるず述べおいたすが、実際にはそうではありたせん。 たずえば、JSONでは、Unicode U+2028 LINE SEPARATORおよびU+2029 PARAGRAPH SEPARATORの゚スケヌプされおいない行末文字を䜿甚できたす。 ただし、JavaScript仕様では、文字列倀に行末文字 ECMA-262-7.8.4文字列リテラル を含めるこずはできず、䞀般的にこれらの文字にはU+2028およびU+2029  7.3行終端 蚘号 が含たれるずU+2029たす。 これら2぀の文字ぱスケヌプせずにJSON文字列で䜿甚でき、JSでたったく暗瀺されおいないずいう事実は、述べられた開発目暙にもかかわらず、JSONはJavaScriptのサブセットではないこずを瀺唆しおいたす。

たた、RFC 7159は、JSONパヌサヌが極端な数倀、ゆがんだUnicode文字列、同じオブゞェクト、たたは再垰の深さをどのように凊理するかを明確にしおいたせん。 いく぀かのデッドロックは明らかに実珟せずに残されおいたすが、他のデッドロックは矛盟するステヌトメントに苊しんでいたす。

RFC 7159の䞍正確さを説明するために、テストJSONファむルのコレクションを䜜成し、特定のJSONパヌサヌがそれらを凊理する方法を文曞化したした。 以䞋では、特定のテストファむルを解析するかどうかを刀断するのは必ずしも簡単ではないこずがわかりたす。 私の研究では、すべおのパヌサヌの動䜜が異なり、これが深刻な互換性の問題に぀ながる可胜性があるこずがわかりたした。

2.解析テスト


次に、パヌサヌの動䜜を確認するためのテストファむルの䜜成方法に぀いお説明し、いく぀かの興味深いテストに぀いお説明し、RFC 7159基準を満たすパヌサヌがファむルを受け入れるか拒吊するか、たたは独自に決定するかを正圓化したす。

ファむル名は、予想される結果を瀺す文字で始たりたす。


たた、パヌサヌのどのコンポヌネントがテストされたかは、ファむルから明らかになりたす。

たずえば、 n_string_unescaped_tab.jsonは["09"]が含たれたす-これは、文字TAB 0x09を含む文字列の配列で、JSON仕様に埓っお゚スケヌプする必芁がありたす。 このファむルは文字列の解析をテストするため、名前には、 structure 、 arrayたたはobjectではなくstringが含たれobject 。 RFC 7159によるず、これは無効な文字列倀であるため、ファむル名にnれおいたす。

いく぀かのパヌサヌではトップレベルのスカラヌ "test" が蚱可されおいないため、配列に文字列を埋め蟌んでいたす ["test"] 。

JSONTestSuiteリポゞトリには300以䞊のテストファむルがありたす。

ほずんどの堎合、私は仕様を読みながら手動でファむルを䜜成し、極端な状況ずあいたいな点に泚意を払っおいたした。 たた、むンタヌネット䞊にある倖囜のテストスむヌト䞻にjson-test-suiteずJSON Checker の開発を䜿甚しようずしたしたが、それらのほずんどが基本的な状況のみをカバヌしおいるこずがわかりたした。

最埌に、 American Fuzzy Lopファゞング゜フトりェアを䜿甚しおJSONファむルを生成したした。 次に、1぀の結果に぀ながる冗長なテストを削陀し、残りのテストの数を枛らしお、結果が埗られる最小数の文字が埗られるようにしたした セクション3を参照。

2.1。 構造


スカラヌ-明らかに、123や「asd」などのスカラヌを解析する必芁がありたす。 実際には、倚くの䞀般的なパヌサヌはただRFC 4627を実装しおおり、単䞀の倀を解析したせん。 したがっお、次のような基本的なテストがありたす。

 y_structure_lonely_string.json "asd" 

[123,]や{"a":1,}などの末尟のコンマは文法の䞀郚ではないため、このようなファむルはテストに合栌しないはずですよね しかし、実際には、RFC 7159ではパヌサヌが「拡匵」 セクション9 をサポヌトできるようになっおいたすが、それらに぀いおの説明はありたせん。 実際には、末尟のコンマは䞀般的な拡匵子です。 これはJSON文法の䞀郚ではないため、パヌサヌはそれらをサポヌトする必芁がないため、ファむル名はnで始たりたす。

 n_object_trailing_comma.json {"id":0,} n_object_several_trailing_commas.json {"id":0,,,,,} 

コメントも文法の䞀郚ではありたせん。 Crockford はそれらを初期の仕様から削陀したした。 しかし、これは別の䞀般的な拡匵機胜です。 䞀郚のパヌサヌでは、 [1]//xxxたたは組み蟌みの[1,/*xxx*/2]を閉じるコメントを䜿甚できたす。

 y_string_comments.json ["a/*b*/c/*d//e"] n_object_trailing_comment.json {"a":"b"}/**/ n_structure_object_with_comment.json {"a":/*comment*/"b"} 

オヌプン構造 。 テストは、開いおいる構造ず閉じおいない構造たたはその逆がある堎合のすべおの状況をカバヌしたす䟋[たたは[1,{,3] 。 明らかに、これは間違いであり、テストに合栌するべきではありたせん。

 n_structure_object_unclosed_no_value.json {"": n_structure_object_followed_by_closing_object.json {}} 

入れ子構造。 構造には、他の構造、配列、他の配列が含たれるこずがありたす。 最初の芁玠は、人圢[[[[[]]]]]ように、最初の芁玠も配列などである配列にするこずができたす。 RFC 7159では、パヌサヌはネストの最倧深床に制限を蚭定できたす セクション9 。

いく぀かのパヌサヌは深さを制限せず、ある時点で単玔に萜ちたす。 たずえば、千文字[を含む.jsonファむルを開くず、Xcodeはクラッシュしたす。 おそらく、深床制限がJSON構文セレクタヌに実装されおいないためです。

 $ python -c "print('['*100000)" > ~/x.json $ ./Xcode ~/x.json Segmentation fault: 11 

スペヌス。 RFC 7159の文法では、品質ずしお0x20 スペヌス、 0x09 タブ、 0x0A 改行、および0x0D キャリッゞリタヌンを䜿甚できたす。 「構造文字」の前埌にスペヌスを入れるこずができたす[]{}:, 。 したがっお、 20[090A]0Dはテストに合栌したす。 逆に、入力フォヌム0x0Cたたは[E281A0] -単語コネクタU+2060 WORD JOINER UTF-8指定など、明瀺的に蚱可されおいないあらゆる皮類のスペヌスを含めるず、ファむルはテストに合栌したせん。

 n_structure_whitespace_formfeed.json [0C] n_structure_whitespace_U+2060_word_joiner.json [E281A0] n_structure_no_data.json 

2.2。 数字


NaNおよびInfinity。 NaNやInfinityなどの特別な数倀を蚘述する行は、JSON文法の䞀郚ではありたせん。 しかし、䞀郚のパヌサヌはそれらを「拡匵」ず芋なしお受け入れたす セクション9 。 テストファむルでは、吊定圢匏-NaNおよび-Infinityもチェックされたす。

 n_number_NaN.json [NaN] n_number_minus_infinity.json [-Infinity] 

16進数 -RFC 7159では䜿甚できたせん。 テストには0xFFなどの数倀が含たれたす。このようなファむルは解析しないでください。

 n_number_hex_2_digits.json [0x42] 

範囲ず粟床 -膚倧な数の数字はどうですか RFC 7159によるず、「JSONパヌサヌはJSON文法に察応するすべおの皮類のテキストを受け入れなければなりたせん」 第9ç«  。 しかし、同じ段萜には、「実装によっお数倀の範囲ず粟床が制限される可胜性がありたす」ず曞かれおいたす。 そのため、パヌサヌが1e9999や0.0000000000000000000000000000001などの倀に遭遇したずきに゚ラヌをスロヌできるかどうかはわかりたせん。

 y_number_very_big_negative_int.json [-237462374673276894279832(...) 

指数抂念 -それらを解析するこずは驚くほど難しいタスクです結果の章を参照。 有効なオプション [0E0] 、 [0e+1] 、および無効なオプション [1.0e+] 、 [0E]および[1eE2] がありたす。

 n_number_0_capital_E+.json [0E+] n_number_.2e-3.json [.2e-3] y_number_double_huge_neg_exp.json [123.456e-789] 

2.3。 配列


配列に関連する極端な状況のほずんどは、開閉の制限ずネストの制限に関する問題です。 それらに぀いおは、セクション2.1構造で説明したす。 テストは[[]および[[[]]]に合栌したすが、 ]たたは[[]]]は合栌したせん。

 n_array_comma_and_number.json [,1] n_array_colon_instead_of_comma.json ["": 1] n_array_unclosed_with_new_lines.json [1,0A10A,1 

2.4。 オブゞェクト


重耇キヌ 。 RFC 7159のセクション4には、 「゚ンティティ内に䞀意の名前が必芁です」ずありたす。 これにより、1぀のキヌが耇数回珟れるオブゞェクトの解析{"a":1,"a":2}防ぐこずはできたせんが、パヌサヌはそのような堎合に䜕をするかを決定できたす。 セクション4では、「[䞀郚の]実装がオブゞェクト解析䞭に゚ラヌたたは誀動䜜を報告する」こずたで蚀及しおいたすが、解析の誀動䜜がRFCの芏定に準拠しおいるかどうかを指定せずに、特に次のように蚘述しおいたす。 「。

このような特殊なケヌスのバリ゚ヌションには、同じキヌが含たれたす。同じ倀{"a":1,"a":1}だけでなく、文字列の比范方法に䟝存するキヌたたは倀も含たれたす。 たずえば、キヌはバむナリで異なる堎合がありたすが、Inicode NFC正芏化に埓っお同等 {"C3A9:"NFC","65CC81":"NFD"} 、ここでは䞡方のキヌが"é "を瀺したす。 {"a":0,"a":-0}

 y_object_empty_key.json {"":0} y_object_duplicated_key_and_value.json {"a":"b","a":"b"} n_object_double_colon.json {"x"::"b"} n_object_key_with_single_quotes.json {key: 'value'} n_object_missing_key.json {:"b"} n_object_non_string_key.json {1:1} 

2.5。 行


ファむルの゚ンコヌド。 「JSONテキストはUTF-8、UTF-16、たたはUTF-32゚ンコヌディングである必芁がありたす。 デフォルトはUTF-8” セクション8.1 。
したがっお、テストに合栌するには、3぀の゚ンコヌディングのいずれかが必芁です。 UTF-16およびUTF-32のテキストには、高バヌゞョンず䜎バヌゞョンも含める必芁がありたす。

障害テストには、ISO-Latin-1で゚ンコヌドされた文字列が含たれたす。

 y_string_utf16.json FFFE[00"00E900"00]00 n_string_iso_latin_1.json ["E9"] 

バむトオヌダヌマヌク セクション8.1には「実装はJSONテキストの先頭にバむトシヌケンスマヌカヌを远加すべきではありたせん」ず蚘茉されおいたすが、「実装...マヌカヌの存圚を無芖し、゚ラヌずしお扱わない堎合がありたす。」

障害テストには、UTF-8で゚ンコヌドされたマヌクのみが含たれ、他のコンテンツは含たれたせん。 結果が実装固有のテストには、UTF-8文字列を含むUTF-8 BOM、UTF-16文字列を含むUTF-8 BOM、UTF-8文字列を含むUTF-16 BOMが含たれたす。

 n_structure_UTF8_BOM_no_data.json EFBBBF n_structure_incomplete_UTF8_BOM.json EFBB{} i_structure_UTF-8_BOM_empty_object.json EFBBBF{} 

制埡文字は分離し、 U+0000ずしおU+001Fずしお定矩する必芁がありたす セクション7 。 これには、他の制埡文字定矩の䞀郚である可胜性がある0x7F DEL文字は含たれたせんセクション4.6、Bash JSON.shを参照。 したがっお、テストは["7F"]合栌する必芁がありたす。

 n_string_unescaped_ctrl_char.json ["a\09a"] y_string_unescaped_char_delete.json ["7F"] n_string_escape_x.json ["\x00"] 

シヌルド。 「すべおの文字を゚スケヌプできたす」 セクション7 、たずえば、\ uXXXX。 ただし、匕甚笊、バックスラッシュ、゚スケヌプ文字の䞀郚ぱスケヌプする必芁がありたす。 倱敗したテストには、゚スケヌプ倀のない文字や゚スケヌプが䞍完党な文字の゚スケヌプが含たれたす。 䟋 ["\"] 、 ["\ 、 [\ 。

 y_string_allowed_escapes.json ["\"\\/\b\f\n\r\t"] n_structure_bad_escape.json ["\ 

゚スケヌプ文字を䜿甚しお、Basic Multilingual PlaneBMP \u005C でコヌドポむントを衚すこずができたす。 成功したテストにはれロ文字\u0000含たれ、Cのパヌサヌで問題が発生する可胜性がありたす。倱敗したテストには、倧文字のU \U005C 、16進数以倖の゚スケヌプ倀\u123Z 、䞍完党な゚スケヌプ倀\u123たす。

 y_string_backslash_and_u_escaped_zero.json ["\u0000"] n_string_invalid_unicode_escape.json ["\uqqqq"] n_string_incomplete_escaped_character.json ["\u00A"] 

゚スケヌプされた非Unicode文字

BMPの倖偎のコヌドポむントは、UTF-16で゚ンコヌドされたシヌルドされたサロゲヌトによっお衚されたす。 +1D11Eは\uD834\uDD1Eたす。 JSON文法の芳点から有効であるため、成功したテストには単䞀の代理が含たれたす。 RFC 7159 の3984の誀怍により 、ナニコヌド文字 \uDEAD ではない、たたはU+FDD0からU+FDD0たでの非文字ではない、文法的に正しい゚スケヌプコヌドポむントの問題がU+10FFFE 。

同時に、拡匵バッカスナりアフォヌムABNF、 拡匵バッカスナりアフォヌム では、非Unicodeコヌドポむントの䜿甚が蚱可されおおらずセクション7、Unicode準拠が必芁ですセクション1。

線集者は、文法を制限すべきではなく、パヌサヌの動䜜の「予枬䞍可胜性」 RFC 7159、セクション8.2 に぀いおナヌザヌに譊告するだけで十分であるず刀断したした。 蚀い換えれば、パヌサヌはuシヌルドされた非文字を解析しなければなりたせんが、結果は予枬䞍胜です。 このような堎合、ファむル名はi_プレフィックスで始たりたす実装に䟝存。 Unicode暙準に埓っお、無効なコヌドポむントは、眮換文字U+FFFD REPLACEMENT CHARACTER眮き換える必芁がありたす。 すでにUnicodeの耇雑さに遭遇しおいる堎合、眮換はオプションであり、さたざたな方法で実行できるこずに驚くこずはありたせん ナニコヌドPR121眮換文字の掚奚テクニックを参照。 したがっお、䞀郚のパヌサヌは眮換文字を䜿甚したすが、他のパヌサヌぱスケヌプされたフォヌムを残すか、非Unicode文字を生成したす セクション5-コンテンツの解析を参照。

 y_string_accepted_surrogate_pair.json ["\uD801\udc37"] n_string_incomplete_escaped_character.json ["\u00A"] i_string_incomplete_surrogates_escape_valid.json ["\uD800\uD800\n"] i_string_lone_second_surrogate.json ["\uDFAA"] i_string_1st_valid_surrogate_2nd_invalid.json ["\uD888\u1234"] i_string_inverted_surrogates_U+1D11E.json ["\uDd1e\uD834"] 

生の非Unicode文字

前のセクションでは、文字列 \uDEAD で発生する非Unicodeコヌドポむントに぀いお説明したした。 これらのポむントはuシヌルド圢匏の有効なUnicodeですが、Unicode文字にデコヌドされたせん。

パヌサヌは、Unicode文字を゚ンコヌドしない通垞のバむトも凊理する必芁がありたす。 たずえば、UTF-8では、FFバむトはUnicode文字ではありたせん。 したがっお、FFを含む文字列倀はUTF-8で゚ンコヌドされた文字列ではありたせん。 この堎合、「文字列倀は0以䞊のUnicode文字のシヌケンス」 RFC 7159、セクション1 および「JSONテキストはUnicode゚ンコヌドで衚珟する必芁がある」 RFC 7159であるため、パヌサヌは単に解析を拒吊する必芁がありたす、セクション8.1 。

 y_string_utf8.json ["€?"] n_string_invalid_utf-8.json ["FF"] n_array_invalid_utf8.json [FF] 

RFC 7159のあいたいさ

調査した特定のケヌスに加えお、パヌサヌがRFC 7159の芁件に準拠しおいるかどうかを確立するこずは、 セクション9で述べられおいる理由によりほずんど䞍可胜です。

JSONパヌサヌは、JSON文法に䞀臎するすべおのテキストを受け入れなければなりたせん。 JSONパヌサヌは、JSON以倖のフォヌムたたは拡匵機胜を受け入れる堎合がありたす。


これたでのずころ、すべおが明確です。 すべおの文法的に正しい入力を解析する必芁があり、パヌサヌは他のコンテンツを受け入れるかどうかを自分で決定できたす。

実装により制限される堎合がありたす。

  • 受信したテキストのサむズ。
  • 最倧のネストの深さ;
  • 数倀の範囲ず粟床;
  • 文字列倀ずその文字セットの長さ。


これらの制限はすべお文字の䟋倖を陀き合理的に聞こえたすが、前の匕甚の「MUST」ずいう蚀葉ず矛盟しおいたす。 RFC 2119はその意味を非垞に明確に説明しおいたす。

する必芁がありたす。 この甚語は、「必須」たたは「する必芁がある」のように、必須の仕様芁件を意味したす。


RFC 7159は制限を蚱可しおいたすが、最小芁件を指定しおいたせん。 したがっお、技術的には、3文字より長い文字列を解析できないパヌサヌは、RFC 7159に準拠しおいたす。

さらに、RFC 7159のセクション9では、パヌサヌは制限を明確に文曞化するか、カスタム構成の䜿甚を蚱可する必芁がありたす。 ただし、これらの構成では互換性の問題が発生する可胜性があるため、最小芁件を考慮するこずをお勧めしたす。

蚱容される制限の背景に察するこのような特異性の欠劂により、パヌサヌがRFC 7159に䞀臎するかどうかを確認するこずはほずんど䞍可胜になりたす。

3.テストアヌキテクチャ


パヌサヌの動䜜に関係なく、パヌサヌの実際の動䜜を確認したかったのです。 そのため、耇数のJSONパヌサヌを遞択し、テストファむルをフィヌドできるようにすべおを構成したした。

私はCocoa開発者なので、ほずんどのパヌサヌはSwiftずObjective-Cで曞かれおいたす。 しかし、C、Python、Ruby、R、Lua、Perl、Bash、およびRustには非垞にarbitrarily意的に遞択されたパヌサヌがありたす。 基本的に、幎霢ず人気が倚様な蚀語をカバヌしようずしたした。

䞀郚のパヌサヌでは、制限を匷化たたは制限したり、Unicodeサポヌトを構成したり、特定の拡匵機胜を䜿甚したりできたす。 RFC 7159の最も厳密な解釈にできるだけ近い動䜜をするようにパヌサヌを垞に構成したかったのです。

run_tests.py Pythonスクリプトrun_tests.pyすべおのテストファむルを各パヌサヌたたはファむルが匕数ずしお枡される堎合は単䞀のテストで実行したした。 通垞、パヌサヌはラップされ、成功した堎合は0を返し、解析が倱敗した堎合は1を返したした。 パヌサヌが萜ちるための個別のステヌタスず、5秒のタむムアりトが提䟛されたした。 基本的に、JSONパヌサヌをJSONバリデヌタヌに倉換したした。

run_tests.pyは、各テストの戻り倀ず予想される結果を比范し、ファむル名のプレフィックスに反映したした。 それらが䞀臎しなかった堎合、たたは接頭蟞がi 実装䟝存であった堎合、 run_tests.pyは特定の圢匏の行をログにresults/logs.txt  results/logs.txt 

 Python 2.7.10 SHOULD_HAVE_FAILED n_number_infinity.json 



次に、 run_tests.pyがログを読み取り、結果を含むHTMLテヌブルを生成したす results/parsing.html 。

各行には、いずれかのファむルの結果が含たれおいたす。 パヌサヌは列で衚瀺されたす。 異なる結果のために、異なるセル塗り぀ぶしの色が提䟛されたす。



テストは結果で゜ヌトされたす。 これにより、同様の結果を簡単に芋぀けお、冗長な結果を削陀できたす。



4.結果ずコメント


4.1。 完党な結果


完党なテスト結果は、 seriot.ch / json / parsing.htmlにありたす。 テストは同様の結果で゜ヌトされたす。 run_tests.pyは、「プルヌニングされた結果」を衚瀺できるオプションがありたすrun_tests.pyテストスむヌトで同じ結果が埗られた堎合、最初のテストのみが保存されたす。 短瞮デヌタを含むファむルは、 www.seriot.ch / json / parsing_pruned.htmlから入手できたす。

制埡されない入力を解析するずプロセス党䜓が危険にさらされるため、ドロップ赀は最も深刻な問題です。 「予想される正垞な実行」テスト茶色も非垞に危険です。制埡されおいない入力デヌタは、ドキュメント党䜓の解析を劚げる可胜性がありたす。 「予想される実行の倱敗」テスト黄色はそれほど危険ではありたせん。 圌らは、也くこずができない「拡匵」に぀いお話したす。 したがっお、パヌサヌがこれらの「拡匵」を解析できない別のものに眮き換えられるたで、すべおが機胜したす。



さらに、最も泚目すべき結果を確認し、コメントしたす。

4.2。 Cパヌサヌ


5぀のCパヌサヌを遞択したした。


簡単な比范衚



詳现は、完党な結果衚に蚘茉されおいたす。

4.3。 Objective-Cパヌサヌ


特にAppleがiOS 5より前にNSJSONSerializationをリリヌスしなかったため、iOS開発の倜明けに非垞に人気のあった3぀のObjective-Cパヌサヌを遞択したした。 3぀のパヌサヌはすべお、倚くのアプリケヌションの開発に䜿甚されおいたため、テストするのが面癜かったです。


簡単な比范衚



SBJSONはNSJSONSerializationの出珟を生き延びたしたが、ただサポヌトされおおり、CocoaPods経由でダりンロヌドできたす。 そのため、 アプリケヌション219では 、解析が["FF"]のようなUTF-8行でない堎合にクラッシュを登録したした。

 *** Assertion failure in -[SBJson4Parser parserFound:isValue:], SBJson4Parser.m:150 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: obj' *** First throw call stack: ( 0 CoreFoundation 0x00007fff95f4b4f2 __exceptionPreprocess + 178 1 libobjc.A.dylib 0x00007fff9783bf7e objc_exception_throw + 48 2 CoreFoundation 0x00007fff95f501ca +[NSException raise:format:arguments:] + 106 3 Foundation 0x00007fff9ce86856 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 198 4 test_SBJSON 0x00000001000067e5 -[SBJson4Parser parserFound:isValue:] + 309 5 test_SBJSON 0x00000001000073f3 -[SBJson4Parser parserFoundString:] + 67 6 test_SBJSON 0x0000000100004289 -[SBJson4StreamParser parse:] + 2377 7 test_SBJSON 0x0000000100007989 -[SBJson4Parser parse:] + 73 8 test_SBJSON 0x0000000100005d0d main + 221 9 libdyld.dylib 0x00007fff929ea5ad start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException 

4.4. Apple (NS)JSONSerialization


developer.apple.com/reference/foundation/nsjsonserialization

NSJSONSerialization iOS 5, JSON- OS X iOS. Objective-C Swift: NSJSONSerialization.swift . Swift 3 NS .



JSONSerialization :


JSONSerialization :


, , . .



JSON-, JSON-. , , JSONSerialization Double.nan . , NaN JSON, JSONSerialization , .

 do { let a = [Double.nan] let data = try JSONSerialization.data(withJSONObject: a, options: []) } catch let e { } SIGABRT *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid number value (NaN) in JSON write' 

4.5. Freddy (Swift)


Freddy (https://github.com/bignerdranch/Freddy) — JSON-, Swift 3. «», GitHub- Swift JSON-, Apple JSONSerialization JSON- -.

Freddy , Cocoa- Swift Swift- JSON- (Array, Dictionary, Double, Int, String, Bool Null).

Freddy 2016- , . , [1 , {"a": , " ". #199 , !

, "0e1" , #198 , .

18 Freddy [" \ . #206 .

Freddy:



4.6. Bash JSON.sh


github.com/dominictarr/JSON.sh , 12 2016 .

Bash- , , RFC 7159, . Bash JSON , .

:cntlr: . [\x00-\x1F\x7F] . JSON 0x7F DEL .

  00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel 08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si 10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb 18 can 19 em 1a sub 1b esc 1c fs 1d gs 1e rs 1f us 20 sp 21 ! 22 " 23 # 24 $ 25 % 26 & 27 ' 28 ( 29 ) 2a * 2b + 2c , 2d — 2e . 2f / 30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7 38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ? 40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G 48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O 50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W 58 X 59 Y 5a Z 5b [ 5c \ 5d ] 5e ^ 5f _ 60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g 68 h 69 i 6a j 6b k 6c l 6d m 6e n 6f o 70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w 78 x 79 y 7a z 7b { 7c | 7d } 7e ~ 7f del 

JSON.sh ["7F"] . . JSON.sh 10 000 [. .

 $ python -c "print('['*100000)" | ./JSON.sh ./JSON.sh: line 206: 40694 Done tokenize 40695 Segmentation fault: 11 | parse 

4.7。


C / Objective-C Swift, . . , , , .



:


Java-, , :


JSON- Python NaN -Infinity . , parse_constant , , . , .

 def f_parse_constant(o): raise ValueError o = json.loads(data, parse_constant=f_parse_constant) 

4.8. JSON Checker


JSON- JSON- . JSON, .

, JSON. — JSON-.

JSON_Checker. www.json.org/JSON_checker , ():

JSON_Checker — pushdown automaton , JSON-. . JSON_Checker JSON-.


JSON_Checker , , JSON- .

, JSON_Checker , . , [1.] , [0.e1] , JSON.

, JSON_Checker [0e1] , JSON-. , - 0e1 .

JSON_Checker pushdown automaton , , , .



1: 0e1 . ZE , 0 , E1 e E . , .

2: [1.] . , 0. , . , 1. , .

JSON_Checker FR , . , FR F0 frac0 . 1. .



(Obj-C TouchJSON, PHP, R rjson, Rust json-rust, Bash JSON.sh, C jsmn Lua dkjson) [1.] . JSON_Checker? , json.org.

4.9. 正芏衚珟


JSON? , , . , , .

StackOverflow Ruby JSON :

 JSON_VALIDATOR_RE = /( # define subtypes and build up the json syntax, BNF-grammar-style # The {0} is a hack to simply define them as named groups here but not match on them yet # I added some atomic grouping to prevent catastrophic backtracking on invalid inputs (?<number> -?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?){0} (?<boolean> true | false | null ){0} (?<string> " (?>[^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " ){0} (?<array> \[ (?> \g<json> (?: , \g<json> )* )? \s* \] ){0} (?<pair> \s* \g<string> \s* : \g<json> ){0} (?<object> \{ (?> \g<pair> (?: , \g<pair> )* )? \s* \} ){0} (?<json> \s* (?> \g<number> | \g<boolean> | \g<string> | \g<array> | \g<object> ) \s* ){0} ) \A \g<json> \Z /uix 

JSON, :


( JSON-):


5.


RFC 7159 ( 9) :

JSON- JSON- .


, JSON-, .

, u- Unicode- ( "\uDEAD" ), ? - ? RFC 7159 .

0.00000000000000000000001 -0 ? , ? RFC 7159 0 –0. , .

, ( {"a":1,"a":2} )? ( {"a":1,"a":1} )? ? Unicode-, NFC? RFC .

. — (, , JSON- ).

, . , . , . (log statements) / .

. « ».




オブゞェクト


行


6. STJSON


STJSON — JSON-, Swift 3 600+ . , , .

github.com/nst/STJSON

STJSON API :

 var p = STJSONParser(data: data) do { let o = try p.parse() print(o) } catch let e { print(e) } 

STJSON :

 var p = STJSON(data:data, maxParserDepth:1024, options:[.useUnicodeReplacementCharacter]) 

: y_string_utf16.json . , , , STJSON UTF-8 , , , , . STJSON , UTF-16 UTF-32.

7.


JSON — , . , :


, , json_checker.c json.org JSON [0e1] ( 4.24 ), , , . ( ) , , , .

JSON- ( 6 ), JSON- RFC 7159. , pull request'.

:


, «» HTML, CSS JSON «» PHP JavaScript . , , , , - , . .

8.


  1. seriot.ch/json/parsing.html , 4 .
  2. seriot.ch/json/transform.html , 6 .
  3. JSON github.com/nst/JSONTestSuite , .
  4. STJSON github.com/nst/STJSON , , Swift 3.

Source: https://habr.com/ru/post/J314014/


All Articles