Regex для анализа одного ключа: значения из JSON в Javascript - PullRequest
13 голосов
/ 06 января 2012

Я пытаюсь выяснить, можно ли найти отдельный keys из строки JSON в Javascript и вернуть Value с помощью Regex.Вроде как создание поискового инструмента 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+"\":","");    
}

Возвращается подстрока Value для Key.

например

getPropFromJSON("Comments")

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

Если вам интересно, почему я хочу сделать это вместо использования JSON.parse(), я строю хранилище документов JSON около localStorage.localStorage поддерживает только пары ключ / значение, поэтому я храню строку JSON всего Document в уникальном Key.Я хочу, чтобы можно было выполнить запрос к документам, в идеале без дополнительных затрат JSON.parsing() всего Collection из Documents, а затем повторно использовать Keys / nested Keys для поиска соответствия.

Я не лучший в regex, поэтому я не знаю, как это сделать, или даже если это возможно только с regex.Это всего лишь эксперимент, чтобы узнать, возможно ли это.Любые другие идеи в качестве решения будут оценены.

Ответы [ 2 ]

25 голосов
/ 06 января 2012

Я бы сильно отговорил вас от этого. 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. Если вы это сделаете, вы могли бы также преобразовать все это с самого начала.

РЕДАКТИРОВАТЬ

Просто чтобы показать, как Regex ломается, вот регулярное выражение, которое пытается проанализировать JSON

Если вы подключите его к http://regexpal.com/, отметив «Dot Matches All». Вы обнаружите, что он может соответствовать некоторым элементам, например:

Regex

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

JSON Matched

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

Regex

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

JSON Matched

"Name": "Humpty"

Однако, как только вы начнете запрашивать более высокие структуры, такие как "Posts", у которых есть вложенные массивы, вы обнаружите, что не можете корректно вернуть структуру, поскольку регулярное выражение не имеет контекста, для которого "]" обозначен конец структуры.

Regex

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

JSON Matched

"Posts": [
  {
      "Title": "How I fell",
      "Comments": [
          { 
              "User":"Fairy God Mother",
              "Comment": "Ha, can't say I didn't see it coming"
          }
      ]
0 голосов
/ 27 марта 2015

Во-первых, зафиксируйте объект JSON. Затем вам нужно сохранить начало и длину совпадающих подстрок. Например:

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

Для строки JSON это работает точно так же (если вы не ищете явно запятые и фигурные скобки, в этом случае я бы рекомендовал какое-то предварительное преобразование вашего объекта JSON перед выполнением регулярного выражения (т.е. think:, {,}) .

Далее вам нужно восстановить объект 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...