Требования к JSON Parser - PullRequest
       21

Требования к JSON Parser

5 голосов
/ 05 января 2009

Я думаю о реализации парсера JSON для Delphi. Что должен делать хороший анализатор JSON? Есть идеи для требований? Я считаю, что это должно по крайней мере выводить и обрабатывать JSON ... Глядя на парсеры XML, должен ли он быть более DOM или SAX-подобным?

Ответы [ 8 ]

4 голосов
/ 10 января 2009

Я думаю, Json.NET отлично справляется с работой.

  • JsonReader и JsonWriter для низких работа на уровне парсинга и вывода JSON
  • JsonSerializer для преобразования объектов в и из JSON
  • Классы JObject, JArray и JValue для работы с JSON в объектной модели

Заметьте, я могу быть немного предвзятым, так как написал это:)

3 голосов
/ 05 января 2009

Хороший пол - это все функции, предоставляемые следующими 3 (взяты из JSON.org ): uJson , JSON Toolkit и lkjson .

2 голосов
/ 05 июня 2011

Когда речь идет о синтаксическом анализе некоторого (текстового) контента, обычно предусматриваются два направления. В мире XML вам обычно приходится выбирать между:

  • Анализатор DOM, который создает древовидную структуру в памяти объектов, отображающих узлы XML;
  • Анализатор SAX, который читает содержимое XML, а затем вызывает предварительно определенные события для каждого элемента содержимого XML.

Фактически, парсеры DOM внутренне используют парсер SAX для чтения содержимого XML. Следовательно, из-за накладных расходов на создание объектов и инициализацию их свойств анализаторы DOM обычно в три-пять раз медленнее, чем SAX. Но DOM-парсеры гораздо более эффективны для обработки данных: как только они отображаются в нативных объектах, код может без промедления обращаться к любому узлу, тогда как доступ на основе SAX должен будет снова прочитать весь XML-контент.

Большинство анализаторов JSON, доступных в Delphi, используют DOM-подобный подход. Например, модуль DBXJSON , включенный в Delphi 2010, или библиотеки SuperObject или DWS создают экземпляр класса, отображающий каждый узел JSON.

В клиентском сервере ORM на основе JSON *1020*, как и у нас, профилирование показывает, что много времени уходит на анализ JSON как на стороне клиента, так и на стороне сервера (на сервере мы конвертируем контент JSON в SQL на лету). Поэтому мы попытались оптимизировать эту часть библиотеки.

Для достижения максимальной скорости мы стараемся использовать смешанный подход:

  • Все необходимые преобразования (например, неэкранированный текст) выполняются в памяти из буфера JSON и внутри него, чтобы избежать выделения памяти;
  • Парсер возвращает указатели на преобразованные элементы (как библиотека vtd-xml ).

Полученная скорость поразительна как для маленького, так и для очень большого буфера содержимого JSON.

Для создания JSON мы также написали несколько быстрых функций сериализации JSON из любого содержимого объекта.

Подробнее и код источника см. В записи этого блога .

2 голосов
/ 16 января 2009

Я реализовал синтаксический анализатор в Java, который я считаю очень удобным для использования. Он анализирует строго соответствующий JSON, с некоторыми принятыми расслаблениями (в основном для моих конкретных целей). Это опубликовано и подробно на моем сайте . Также опубликован дополнительный метод, который иллюстрирует загрузку документа с использованием синтаксического анализатора - так что вы можете использовать его как ориентированный на поток, так и ориентированный на документ.

Я настоятельно рекомендую parsng в стиле pull (у меня есть также синтаксический анализатор XML).

2 голосов
/ 06 января 2009

Я использовал инструментарий JSON в нескольких проектах с большим успехом. В какой-то момент я изменил только то, как он форматирует полученный JSON, но это вопрос личного вкуса.

Это бесплатно, довольно чисто и просто в использовании. Нет необходимости устанавливать пакеты; просто есть файл .pas где-то на вашем пути. Просто проверьте test_usage.dpr ниже для нескольких простых примеров того, как его использовать. Это не намного легче, чем это.

Я бы не стал тратить свое время на попытку реализовать еще один синтаксический анализатор JSON, если только вы не хотите делать это в образовательных целях, и в этом случае вам все равно следует тщательно изучить существующие реализации.

JSON Toolkit home: http://www.progdigy.com/?page_id=6

program test_usage;
{$IFDEF FPC}
  {$MODE OBJFPC}{$H+}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

uses
  SysUtils,
  superobject;

var
  my_string, my_int, my_object, my_array: ISuperObject;
  new_obj: ISuperObject;
  j: integer;
  ite: TSuperObjectIter;

begin
  try
    my_string := TSuperObject.Create(#9);
    writeln('my_string=', my_string.AsString);
    writeln('my_string.AsJSon=', my_string.AsJSon);

    my_string := TSuperObject.Create('foo');
    writeln('my_string=', my_string.AsString);
    writeln('my_string.AsJson=', my_string.AsJson);

    my_int := TSuperObject.Create(9);
    writeln('my_int=', my_int.AsInteger);
    writeln('my_int.AsJson=', my_int.AsJson);

    my_array := TSuperObject.Create(stArray);
    my_array.I[''] := 1; // append
    my_array.I[''] := 2; // append
    my_array.I[''] := 3; // append
    my_array.I['4'] := 5;
    writeln('my_array=');
    with my_array.AsArray do
    for j := 0 to Length - 1 do
      if O[j] = nil then
        writeln(#9'[', j,']=', 'null') else
        writeln(#9'[', j,']=', O[j].AsJson);
    writeln('my_array.AsJson=', my_array.AsJson);

    my_object := TSuperObject.Create(stObject);
    my_object.I['abc'] := 12;
   // my_object.S['path.to.foo[5]'] := 'bar';
    my_object.B['bool0'] := false;
    my_object.B['bool1'] := true;
    my_object.S['baz'] := 'bang';
    my_object.S['baz'] := 'fark';
    my_object.AsObject.Delete('baz');
    my_object['arr'] := my_array;
    writeln('my_object=');
    if ObjectFindFirst(my_object, ite) then
    repeat
      writeln(#9,ite.key,': ', ite.val.AsJson);
    until not ObjectFindNext(ite);
    ObjectFindClose(ite);
    writeln('my_object.AsJson=', my_object.AsJson);

    new_obj := TSuperObject.Parse('"003"');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('/* hello */"foo"');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('// hello'#10'"foo"');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('"\u0041\u0042\u0043"');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('null');
    if new_obj = nil then
      writeln('new_obj.AsJson=', 'null');

    new_obj := TSuperObject.Parse('true');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('12');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('12.3');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('["\n"]');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('["\nabc\n"]');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('[null]');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('[]');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('["abc",null,"def",12]');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{}');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{ "foo": "bar" }');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{ "foo": "bar", "baz": null, "bool0": true }');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{ "foo": [null, "foo"] }');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] }');
    writeln('new_obj.AsJson=', new_obj.AsJson);

    new_obj := TSuperObject.Parse('{ foo }');
    if (new_obj = nil) then
      writeln('got error as expected');

    my_string := nil;
    my_int := nil;
    my_object := nil;
    my_array := nil;
    new_obj := nil;


    writeln(#10'press enter ...');
    readln;
  except
    on E: Exception do
      writeln(E.Message)
  end;
end.
1 голос
/ 15 января 2009

Я согласен с Джеймсом; Есть 3 разумных способа работы с Json: поток событий / токенов; в виде дерева (например, XML DOM) или путем привязки к / от «нативных» объектов. Пакет, с которым я знаком, - это Джексон (http://jackson.codehaus.org),), который также поддерживает эти 3 метода, подобно тому, как (я предполагаю) Json.NET.

0 голосов
/ 06 июня 2011

Jettison (http://jettison.codehaus.org/) - это популярная реализация JSON StAX (Streaming API for XML), написанная на Java.

Jettison - это набор API Java (как STaX и DOM), которые читают и написать JSON. Это позволяет почти прозрачное включение на основе JSON веб-сервисы в сервисах как CXF или XML сериализация фреймворки, такие как XStream.

0 голосов
/ 05 января 2009

Хорошо, что в JSON есть то, что он использует довольно простую грамматику, а написание парсера для него довольно просто. «забыв» о всех других реализациях, но используя Delphi, я бы начал с класса TParser в модуле классов для быстрого запуска. Создайте отдельные методы для обработки каждого элемента (некоторые уже сделаны в TParser, поэтому я предложил начать с этого момента).

Теперь, что делать с тем, что вы проанализировали. Здесь начинается самое интересное. Если вы имитируете интерфейсы и реализацию TXmlDocument, то преобразование в / из XML / JSON несколько тривиально.

...