5

我正在考虑为 Delphi 实现 JSON 解析器。一个好的 JSON 解析器应该做什么?有关要求的任何想法?我相信它至少应该输出和处理 JSON……看看 XML 解析器,它应该更像 DOM 还是更像 SAX?

4

8 回答 8

4

我认为Json.NET做得很好。

  • JsonReader 和 JsonWriter 用于解析和输出 JSON 的低级工作
  • 用于将对象与 JSON 相互转换的 JsonSerializer
  • 用于在对象模型中处理 JSON 的 JObject、JArray 和 JValue 类

请注意,因为我写了它,所以我可能有点偏见:)

于 2009-01-09T21:28:17.977 回答
3

以下 3 个(取自JSON.org)提供的所有功能最好是:uJsonJSON Toolkitlkjson

于 2009-01-05T14:02:51.377 回答
2

我在几个项目中使用了 JSON 工具包,并取得了巨大的成功。我在某些时候唯一修改的是它格式化结果 JSON 的方式,但这是个人喜好问题。

它是免费的,相当干净且易于使用。无需安装包;只需在路径中的某处有一个 .pas 文件。只需检查下面的test_usage.dpr以获取有关如何使用它的一些简单示例。没有比这更容易的了。

我不会浪费时间尝试实现另一个 JSON 解析器,除非您出于教育目的而这样做,在这种情况下,无论如何您都应该仔细研究现有的实现。

JSON 工具包主页: 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 回答
2

当它处理解析一些(文本)内容时,通常设想两个方向。在 XML 世界中,您通常必须在以下选项中做出选择:

  • 一个 DOM 解析器,它创建映射 XML 节点的对象的内存树结构;
  • 一个 SAX 解析器,它读取 XML 内容,然后为每个 XML 内容元素调用预定义的事件。

事实上,DOM 解析器在内部使用 SAX 解析器来读取 XML 内容。因此,由于对象创建及其属性初始化的开销,DOM 解析器通常比 SAX 慢三到五倍。但是,DOM 解析器在处理数据方面要强大得多:一旦它被映射到本地对象中,代码就可以立即访问任何给定节点,而基于 SAX 的访问将不得不再次读取整个 XML 内容。

Delphi 中可用的大多数 JSON 解析器都使用类似 DOM 的方法。例如,自 Delphi 2010 起包含的DBXJSON单元或SuperObjectDWS库创建映射每个 JSON 节点的类实例。

在像我们这样的基于 JSON 的客户端-服务器 ORM中,分析表明在客户端和服务器端(在服务器端,我们将 JSON 内容动态转换为 SQL)都花费了大量时间进行 JSON 解析。因此,我们尝试优化这部分库。

为了达到最佳速度,我们尝试使用混合方法:

  • 所有必要的转换(例如非转义文本)都在内存中、从 JSON 缓冲区中进行,以避免内存分配;
  • 解析器返回指向转换后元素的指针(就像vtd-xml 库一样)。

对于小型和非常大的 JSON 内容缓冲区,生成的速度是惊人的。

为了生成 JSON,我们还从任何对象内容编写了一些快速的 JSON 序列化函数。

有关详细信息和代码源,请参阅此博客的条目

于 2011-06-05T06:29:53.783 回答
1

我同意詹姆斯的观点;使用 Json 有 3 种明智的方法:作为事件/令牌流;作为树(如 XML DOM),或通过绑定到/来自“本机”对象。我熟悉的包是 Jackson(http://jackson.codehaus.org),它也支持这 3 种方法,类似于(我假设)Json.NET 所做的。

于 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/) 是一种流行的 JSON StAX(XML 流 API)实现,用 Java 编写。

Jettison 是读取和写入 JSON 的 Java API(如 STaX 和 DOM)的集合。这允许在服务框架(如 CXF)或 XML 序列化框架(如 XStream)中几乎透明地启用基于 JSON 的 Web 服务。

于 2011-06-06T10:31:09.963 回答