1. ホーム
  2. javascript

[解決済み】jQuery.parseJSONでJSONのシングルクォートがエスケープされているため、「無効なJSON」エラーが発生する。

2022-04-19 07:44:38

質問

サーバへのリクエストは jQuery.post() で、サーバーはJSONオブジェクトを返しています( { "var": "value", ... } ). しかし、値のどれかにシングルクオート (適切にエスケープされており、たとえば \' ) 、jQueryは、他の有効なJSON文字列をパースするのに失敗します。以下は、私が言いたいことの例です ( Chromeのコンソールで行う ):

data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }

$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }

これって普通なんでしょうか?JSON経由で単一の引用符を適切に渡す方法はないのでしょうか?

解決方法は?

のステートマシン図によると JSONサイト エスケープされたダブルクォート文字のみが許可され、シングルクォート文字は許可されません。シングルクォート文字はエスケープする必要がありません。



更新情報 - ご興味のある方は、より詳しい情報をご覧ください。


Douglas Crockford氏は、JSON仕様が文字列内のシングルクォートのエスケープを許可しない理由について、特に述べていません。しかし、JSONに関する彼の議論の中で JavaScriptの付録E。良いところ と、彼は書いている。

<ブロッククオート

JSONの設計目標は、最小限であること、移植性があること、テキストであること、そしてJavaScriptのサブセットであることでした。相互運用のために合意する必要が少なければ少ないほど、相互運用が容易になります。

つまり、すべてのJSON実装が合意しなければならないルールが1つ減るので、ダブルクォートを使った文字列の定義のみを許可することにしたのでしょう。その結果、文字列内のシングルクォート文字が、誤って文字列を終了させることは不可能になりました。なぜなら、定義上、文字列はダブルクォート文字によってのみ終了させることができるからです。したがって、正式な仕様では、一文字の引用符のエスケープを許可する必要はありません。


もう少し掘り下げると、クロックフォードの org.json Java用のJSONの実装は、より許容範囲が広いし が行います。 はシングルクオートキャラクタを許可します。

<ブロッククオート

toStringメソッドで生成されるテキストは、JSONの構文規則に厳密に従ったものです。コンストラクタは、受け入れるテキストについてより寛容です。

...

  • 文字列は、'(シングルクォート)で引用することができます。

によって確認されます。 JSONTokener のソースコードです。その nextString メソッドは、エスケープされたシングルクォート文字を受け入れ、ダブルクォート文字と同じように扱います。

public String nextString(char quote) throws JSONException {
    char c;
    StringBuffer sb = new StringBuffer();
    for (;;) {
        c = next();
        switch (c) {

        ...

        case '\\':
            c = this.next();
            switch (c) {

            ...

            case '"':
            case '\'':
            case '\\':
            case '/':
                sb.append(c);
                break;
        ...

メソッドの先頭には、情報提供のためのコメントがあります。

正式なJSON形式では、一重引用符で囲まれた文字列は認められませんが、実装では受け入れることができます。

そのため、シングルクォートを受け入れる実装もありますが、これに依存してはいけません。多くの一般的な実装はこの点で非常に厳しく、シングルクォートされた文字列やエスケープされたシングルクォートを含むJSONは拒否されるでしょう。


最後に、最初の質問と関連付けます。 jQuery.parseJSON は、まずブラウザのネイティブJSONパーサーか、または、以下のようなロードされたライブラリを使用しようとします。 json2.js の場合、jQueryのロジックはこのライブラリに基づいています。 JSON が定義されていない場合)。したがって、jQueryは、その基礎となる実装と同じくらい寛容であることができます。

parseJSON: function( data ) {
    ...

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

    ...

    jQuery.error( "Invalid JSON: " + data );
},

私の知る限り、これらの実装は公式のJSON仕様にのみ準拠しており、シングルクォートを受け付けないため、jQueryもそうなっています。