Подтвердить что ты не робот

Регулярное выражение для анализа массива объектов JSON?

Я пытаюсь разобрать массив объектов JSON в массив строк в С#. Я могу извлечь массив из объекта JSON, но я не могу разбить строку массива на массив отдельных объектов.

У меня есть эта тестовая строка:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

Сейчас я использую следующие регулярные выражения, чтобы разделить элементы на отдельные объекты. Пока что они являются двумя отдельными регулярными выражениями, пока я не исправил проблему со вторым:

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

Регулярное выражение arrayFinder работает так, как я ожидал, но по причинам, которые я не понимаю, регулярное выражение arrayParser не работает вообще. Все, что я хочу сделать, это разделить отдельные элементы на свои собственные строки, поэтому я получаю список, подобный этому:

{id:0,name:"Lorem Ipsum"}
{id:1,name:"Lorem Ipsum"}
{id:2,name:"Lorem Ipsum"}

Является ли этот список массивом string[] или коллекцией Group или Match неважно, но я не понимаю, как получить разбиение объектов. Используя строку arrayParser и json, указанную выше, я пробовал этот код, который, как я предполагал, будет работать без везения:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

string array = arrayFinder.Match(json).Groups["items"].Value;
// At this point the 'array' variable contains: 
// {id:0,name:"Lorem Ipsum"},{id:1,name:"Lorem Ipsum"},{id:2,name:"Lorem Ipsum"}

// I would have expected one of these 2 lines to return 
// the array of matches I'm looking for
CaptureCollection c = arrayParser.Match(array).Captures;
GroupCollection g = arrayParser.Match(array).Groups;

Кто-нибудь может понять, что я делаю неправильно? Я полностью застрял в этом.

4b9b3361

Ответ 1

Сбалансированные круглые скобки - это буквально пример учебника языка, который не может обрабатываться с помощью регулярных выражений. JSON - это, по существу, сбалансированные круглые скобки плюс множество других вещей, а фигурные скобки заменены на parens. В иерархии формальных языков JSON - это контекстно-свободный язык. Регулярные выражения не могут анализировать контекстно-свободные языки.

Некоторые системы предлагают расширения для регулярных выражений, которые sort-sorta обрабатывают сбалансированные выражения. Однако они все уродливые хаки, они все не переносятся, и все они в конечном счете являются неправильным инструментом для этой работы.

В профессиональной работе вы почти всегда будете использовать существующий парсер JSON. Если вы хотите бросить свои собственные для образовательных целей, я бы предложил начать с простой арифметической грамматики, которая поддерживает + - */(). (У JSON есть некоторые правила экранирования, которые, хотя и не сложны, сделают вашу первую попытку сложнее, чем она должна быть.) В основном вам нужно:

  • Разложите язык в алфавит символов
  • Напишите контекстно-свободную грамматику в терминах тех символов, которые распознают язык
  • Преобразуйте грамматику в нормальную форму Хомского или достаточно близко, чтобы сделать шаг 5 простым.
  • Напишите лексер, который преобразует исходный текст в ваш вводный алфавит
  • Напишите рекурсивный синтаксический анализатор спуска, который выводит ваш лексер, анализирует его и производит какой-то вывод

Это типичное трехлетнее назначение CS практически в любом университете.

Следующий шаг - выяснить, насколько сложна строка JSON, необходимая для запуска в вашем рекурсивном синтаксическом анализаторе. Затем посмотрите на другие типы парсеров, которые могут быть написаны, и вы поймете, почему каждый, кто должен разбирать контекстно-свободный язык в реальном мире, использует инструмент, например yacc или antlr, вместо написания парсера вручную.

Если вам нужно больше учиться, чем вы искали, тогда вы можете свободно использовать готовый парсер JSON, усыновленный тем, что вы узнали что-то важное и полезное: пределы регулярных выражений.

Ответ 2

Сбалансированные круглые скобки являются буквально примером учебника языка, который не может обрабатываться с помощью регулярных выражений

bla bla bla... проверьте это:

arrayParser = "(?<Key>[\w]+)":"?(?<Value>([\s\w\d\.\\\-/:_]+(,[,\s\w\d\.\\\-/:_]+)?)+)"?

это работает для меня

если вы хотите совместить пустые значения, измените последние '+' на '*'

Ответ 3

Используете ли вы .NET 3.5? Если это так, вы можете использовать DataContractJsonSerializer, чтобы проанализировать это. Нет причин для этого.

Если вы не используете .NET 3.5, вы можете использовать Jayrock.

Ответ 4

public Dictionary<string, string> ParseJSON(string s)
{
    Regex r = new Regex("\"(?<Key>[\\w]*)\":\"?(?<Value>([\\s\\w\\d\\.\\\\\\-/:_\\+]+(,[,\\s\\w\\d\\.\\\\\\-/:_\\+]*)?)*)\"?");
    MatchCollection mc = r.Matches(s);

    Dictionary<string, string> json = new Dictionary<string, string>();

    foreach (Match k in mc)
    {
        json.Add(k.Groups["Key"].Value, k.Groups["Value"].Value);

    }
    return json;
}

Эта функция реализует регулярное выражение Лукаша. Я добавляю только к склону + char для оценки группы (потому что я использую это для синтаксического анализа токена live connect)

Ответ 5

JSON обычно не анализируется регулярными выражениями (некоторые чрезвычайно упрощенные варианты JSON могут, но тогда они не JSON, а что-то еще).

Вам нужен фактический синтаксический анализатор для правильного анализа JSON.

И вообще, почему вы пытаетесь разобрать JSON? Есть многочисленные библиотеки, которые могут сделать это за вас, и намного лучше, чем ваш код. Зачем изобретать колесо, когда колесо factory за углом со словами FOSS над дверью?