web-dev-qa-db-ja.com

単一のキーを解析するための正規表現:JavaScriptのJSONからの値

Javascriptでkeys文字列から個々のJSONを検索して、ValueRegexで返すことができるかどうかを確認しようとしています。 JSON検索ツールを構築するようなものです。

次のJSONを想像してください

"{
    "Name": "Humpty",
    "Age": "18",
    "Siblings" : ["Dracula", "Snow White", "Merlin"],
    "Posts": [
        {
            "Title": "How I fell",
            "Comments": [
                { 
                    "User":"Fairy God Mother",
                    "Comment": "Ha, can't say I didn't see it coming"
                }
            ]
        }
    ]
}"

JSON文字列を検索して、個々のプロパティのみを取得できるようにしたいのですが。

すでにfunctionであると想定すると、次のようになります。

function getPropFromJSON(prop, JSONString){
    // Obviously this regex will only match Keys that have
    // String Values.
    var exp = new RegExp("\""+prop+"\"\:[^\,\}]*");
    return JSONString.match(exp)[0].replace("\""+prop+"\":","");    
}

ValueKeyのサブストリングを返します。

例えば.

getPropFromJSON("Comments")

> "[
    { 
        "User":"Fairy God Mother",
        "Comment": "Ha, can't say I didn't see it coming"
    }
]"

JSON.parse()を使用する代わりになぜこれを実行するのか疑問に思われる場合は、localStorageの周りにJSONドキュメントストアを構築しています。 localStorageはキーと値のペアのみをサポートするため、JSON全体のDocument文字列を一意のKeyに格納します。ドキュメントでクエリを実行できるようにしたいのですが、理想的には、CollectionDocuments全体のJSON.parsing()のオーバーヘッドなしに、Keys/nested Keysを再帰的に検索して一致を見つけます。

私はregexが得意ではないので、これを行う方法がわからないか、またはregexだけでも可能かどうかはわかりません。これは、それが可能かどうかを確認するための実験にすぎません。解決策として他のアイデアがあれば幸いです。

13
AshHeskes

私はあなたがこれをすることを強くお勧めしません。ここで明確に述べられているように、JSONは通常の言語ではありません: https://cstheory.stackexchange.com/questions/3987/is-json-a-regular-language

上記の投稿から引用するには:

たとえば、配列の配列の配列を考えます。

[ [ [ 1, 2], [2, 3] ] , [ [ 3, 4], [ 4, 5] ] ] 

明らかに、それを真の正規表現で解析することはできません。

JSONをオブジェクト(JSON.parse)に変換し、構造を走査するための検索機能を実装することをお勧めします。

それ以外に、ダグラス・クロックフォードの json2.js 解析メソッドの要点を見ることができます。おそらく、変更されたバージョンでは、JSON文字列を検索して、構造全体をオブジェクトに変換せずに、探していた特定のオブジェクトを返すことができます。これは、JSONから他のデータを取得しない場合にのみ役立ちます。もしそうなら、あなたも最初から全部を変えたかもしれません。

[〜#〜]編集[〜#〜]

正規表現がどのように機能しないかをさらに示すために、JSONを解析しようとする正規表現を次に示します

それを http://regexpal.com/ にプラグインすると、「Dot Matches All」がチェックされます。あなたはそれがいくつかの要素にうまくマッチできることがわかります:

正規表現

"Comments"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\") 

JSON一致

"Comments": [
                { 
                    "User":"Fairy God Mother",
                    "Comment": "Ha, can't say I didn't see it coming"
                }
            ]

正規表現

"Name"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\")

JSON一致

"Name": "Humpty"

ただし、ネストされた配列を持つ「Posts」などのより高い構造のクエリを開始するとすぐに、「]」が指定された終わりであるというコンテキストが正規表現にないため、構造を正しく返すことができないことがわかります。構造。

正規表現

"Posts"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\")

JSON一致

"Posts": [
  {
      "Title": "How I fell",
      "Comments": [
          { 
              "User":"Fairy God Mother",
              "Comment": "Ha, can't say I didn't see it coming"
          }
      ]
26
Brandon Boone

まず、JSONオブジェクトを文字列化します。次に、一致した部分文字列の開始と長さを格納する必要があります。例えば:

"matched".search("ch") // yields 3

JSON文字列の場合、これはまったく同じように機能します(カンマと中かっこを明示的に検索している場合を除く)。この場合、正規表現を実行する前に、JSONオブジェクトを事前に変換することをお勧めします(例::、{、})。

次に、JSONオブジェクトを再構築する必要があります。私が作成したアルゴリズムは、一致インデックスから逆方向に再帰的に戻ることでJSON構文を検出することでこれを行います。たとえば、疑似コードは次のようになります。

find the next key preceding the match index, call this theKey
then find the number of all occurrences of this key preceding theKey, call this theNumber
using the number of occurrences of all keys with same name as theKey up to position of theKey, traverse the object until keys named theKey has been discovered theNumber times
return this object called parentChain

この情報を使用すると、正規表現を使用してJSONオブジェクトをフィルタリングし、キー、値、および親オブジェクトチェーンを返すことができます。

私が作成したライブラリとコードは http://json.spiritway.co/ で確認できます。

0
mikewhit