5

Delphi用のJSONパーサーの実装を考えています。優れたJSONパーサーは何をすべきですか?要件に関するアイデアはありますか?少なくともJSONを出力して処理する必要があると思います...XMLパーサーを見ると、もっとDOMまたはSAXに似ている必要がありますか?

4

8 に答える 8

4

Json.NETは非常に優れた仕事をしていると思います。

  • JSON の解析と出力の低レベル作業用の JsonReader と JsonWriter
  • オブジェクトを JSON との間で変換するための JsonSerializer
  • オブジェクト モデルで JSON を操作するための JObject、JArray、および JValue クラス

私がそれを書いたので、私は少し偏見があるかもしれないことに注意してください:)

于 2009-01-09T21:28:17.977 に答える
3

適切なフロアは、次の3つ( JSON.orgから取得)によって提供されるすべての機能です:uJsonJSON Toolkit、およびlkjson

于 2009-01-05T14:02:51.377 に答える
2

一部の (テキスト) コンテンツの解析を扱う場合、通常は 2 つの方向が想定されます。XML の世界では、通常、次のいずれかを選択する必要があります。

  • XML ノードをマッピングするオブジェクトのメモリ内ツリー構造を作成する DOM パーサー。
  • XML コンテンツを読み取る SAX パーサーは、XML コンテンツ要素ごとに定義済みのイベントを呼び出します。

実際、DOM パーサーは内部で SAX パーサーを使用して XML コンテンツを読み取ります。したがって、オブジェクトの作成とそのプロパティの初期化のオーバーヘッドにより、DOM パーサーは通常、SAX よりも 3 倍から 5 倍遅くなります。しかし、DOM パーサーはデータの処理に関してはるかに強力です。データがネイティブ オブジェクトにマップされるとすぐに、コードは任意のノードにすぐにアクセスできますが、SAX ベースのアクセスでは XML コンテンツ全体を再度読み取る必要があります。

Delphi で利用可能なほとんどの JSON パーサーは、DOM に似たアプローチを使用します。たとえば、Delphi 2010 以降に含まれているDBXJSONユニット、またはSuperObjectまたはDWSライブラリは、各 JSON ノードをマッピングするクラス インスタンスを作成します。

私たちのようなJSON ベースのクライアント/サーバー ORMでは、プロファイリングにより、クライアント側とサーバー側の両方で JSON の解析に多くの時間が費やされていることがわかります (サーバーでは、JSON コンテンツをオンザフライで SQL に変換します)。したがって、ライブラリのこの部分を最適化しようとしました。

最高の速度を達成するために、混合アプローチを使用しようとします。

  • 必要なすべての変換 (エスケープ解除テキストなど) は、メモリ割り当てを回避するために、JSON バッファから、および JSON バッファ内でメモリ内で行われます。
  • パーサーは、変換された要素へのポインターを返します ( vtd-xml ライブラリーと同様)。

結果として得られる速度は、JSON コンテンツ バッファーが小さい場合でも非常に大きい場合でも、驚くべきものです。

JSON を生成するために、任意のオブジェクト コンテンツから高速な JSON シリアライゼーション関数もいくつか作成しました。

詳細とコード ソースについては、このブログのエントリを参照してください。

于 2011-06-05T06:29:53.783 に答える
2

私はいくつかのプロジェクトで JSON ツールキットを使用しており、大きな成功を収めています。ある時点で変更したのは、結果の JSON をフォーマットする方法だけでしたが、それは個人的な好みの問題です。

無料で、かなりきれいで、使いやすいです。パッケージをインストールする必要はありません。パスのどこかに .pas ファイルがあるだけです。以下のtest_usage.dprを確認して、使用方法の簡単な例を確認してください。それはそれほど簡単ではありません。

もう 1 つの JSON パーサーを実装しようとして時間を無駄にすることはありません。ただし、教育目的で実装する場合を除きます。その場合は、いずれにせよ既存の実装を注意深く調査する必要があります。

JSON Toolkit ホーム: 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.
于 2009-01-06T03:35:03.547 に答える
2

私は Java でプル スタイルのパーサーを実装しました。これは非常に使いやすいと思います。厳密に準拠した JSON を解析し、いくつかの緩和を受け入れます (主に私の特定の目的のため)。それは私のウェブサイトで公開され、詳細に説明されています。また、パーサーを使用したドキュメントのロードを示す追加のメソッドも公開されているため、ストリーム指向またはドキュメント指向のいずれでも使用できます。

プル スタイルの解析を強くお勧めします (プル型の XML パーサーも持っています)。

于 2009-01-16T07:25:25.457 に答える
1

私はジェームズに同意します。Jsonを操作するための3つの賢明な方法があります。イベント/トークンのストリームとして。ツリーとして(XML DOMのように)、または「ネイティブ」オブジェクトにバインドしたり、オブジェクトからバインドしたりします。私がよく知っているパッケージはJackson(http://jackson.codehaus.org)であり、Json.NETと同様に、これら3つのメソッドもサポートしています。

于 2009-01-15T06:13:33.763 に答える
0

JSONの良いところは、かなり単純な文法を使用し、そのためのパーサーを作成するのがかなり簡単なことです。他のすべての実装を「忘れる」が、Delphiを使用して、ジャンプスタートのためにクラスユニットのTParserクラスから始める。各要素を処理するための個別のメソッドを作成します(一部はすでにTParserで実行されているため、そこから開始することをお勧めします)。

さて、あなたが解析したものをどうするか。楽しみが生まれるところがあります。TXmlDocumentのインターフェースと実装を模倣する場合、XML/JSONとの間の変換はやや簡単です。

于 2009-01-05T19:54:14.803 に答える
0

Jettison(http://jettison.codehaus.org/)は、Javaで記述された人気のあるJSON StAX(Streaming API for XML)実装です。

Jettisonは、JSONの読み取りと書き込みを行うJava API(STaXやDOMなど)のコレクションです。これにより、CXFなどのサービスフレームワークまたはXStreamなどのXMLシリアル化フレームワークでJSONベースのWebサービスをほぼ透過的に有効にできます。

于 2011-06-06T10:31:09.963 に答える