【问题标题】:How do I pretty-print JSON in Delphi?如何在 Delphi 中漂亮地打印 JSON?
【发布时间】:2013-08-29 12:42:44
【问题描述】:

我正在寻找一个函数,该函数将 JSON 字符串作为输入并使用换行符和缩进(制表符)对其进行格式化。

示例: 我有输入线:

{"menu": {"header": "JSON viewer", "items": [{"id": "Delphi"},{"id": "Pascal", "label": "Nice tree format"}, null]}}

并希望得到一个可读的文本结果:

{
   "menu":{
      "header":"JSON viewer",
      "items":[
       {
         "id":"Delphi"
       },
       {
         "id":"Pascal",
         "label":"Nice tree format"
       },
       null
      ]
   }
}

我找到了很多 PHP 和 C# 的示例,但不是 Delphi。 有人可以帮忙实现这样的功能吗?

更新 - 使用 SuperObject 的解决方案:

function FormatJson (InString: WideString): string; // Input string is "InString"
var
  Json : ISuperObject;
begin
  Json := TSuperObject.ParseString(PWideChar(InString), True);
  Result := Json.AsJson(true, false); //Here comes your result: pretty-print JSON
end;

【问题讨论】:

  • 很高兴分享答案。
  • 如果您只是将输入参数类型更改为WideString,则不需要任何该转换代码;每当您调用FormatJson 时,编译器都会自动执行等效任务。只需更改类型,即可将前七行替换为Json := TSuperObject.ParseString(PWideChar(InString), True)

标签: json delphi formatting pascal pretty-print


【解决方案1】:

如果您不想使用任何外部库,并且您使用的是 delphi XE5 或更新版本,那么 REST.Json 单元中有一个非常方便的 TJson.Format() 函数。

uses json, REST.Json;

{ ... }    

function FormatJSON(json: String): String;
var
  tmpJson: TJsonObject;
begin
  tmpJson := TJSONObject.ParseJSONValue(json);
  Result := TJson.Format(tmpJson);

  FreeAndNil(tmpJson);
end;

【讨论】:

  • 请注意,从 Delphi Berlin Update 2 开始,TJson.Format 函数会产生人类可读但与 Json 不兼容的输出,因为它除了双引号外不能正确转义任何内容。
  • 在 Tokio tmpJson 必须是 TJsonValue:function FormatJSON(json: String): String; var tmpJson: TJsonValue; begin tmpJson := TJSONObject.ParseJSONValue(json); Result := TJson.Format(tmpJson); FreeAndNil(tmpJson); end;
【解决方案2】:

您也可以使用我们开源SynCommons.pas单元的following methods

var json,new: RawUTF8;
begin
  json := '{"menu": {"header": "JSON viewer", "items": [{"id": "Delphi"},{"id": "Pascal", "label": "Nice tree format"}, null]}}';
  new := JSONReformat(json,jsonHumanReadable);
  ...

这里new 将包含:

{
  "menu": {
    "header": "JSON viewer",
    "items": 
    [
      {
        "id": "Delphi"
      },
      {
        "id": "Pascal",
        "label": "Nice tree format"
      },
      null
    ]
  }
}

如果您使用jsonUnquotedPropName 格式:

  new := JSONReformat(json,jsonUnquotedPropName);

您将获得以下扩展语法(类似于 JavaScriptMongoDB shell 中使用的语法):

{
  menu: {
    header: "JSON viewer",
    items: 
    [
      {
        id: "Delphi"
      },
      {
        id: "Pascal",
        label: "Nice tree format"
      },
      null
    ]
  }
}

此语法被接受为我们开源框架的所有 JSON 函数的有效输入,作为默认 JSON 语法的替代。我们发现它非常有用,例如用于配置文件。

请注意,我们的JSONReformat() 函数非常快。它可以在 1.4 秒内将来自 CityLots 的 190 MB 无法格式化的巨大 JSON 内容转换为 400 MB 的美化 JSON(预期和带有行字段)。 SuperObject 仅能在 10 秒内读取它,并且仅使用 1.1 GB 来存储 190 MB 的内容。而且 DBXJSON 甚至无法加载数据:它消耗所有 32 位内存 - 在 Win64 (XE6) 下,需要 50 秒并使用 3 GB 的 RAM 来读取 190 MB 的 JSON。见this article for some numbers

【讨论】:

  • 注意:我们的SynCommons.pas 单元适用于从 Delphi 6 到 XE6,在 Win32 和 Win64 平台上,并且完全支持 Unicode,即使在您仍在使用的 Delphi 7 修订版上也是如此。实际上,该单元(以及这个JSONReformat() 函数)直接以UTF-8 完成所有过程,而无需将数据分配到stringwidestring 的任何内存。只需使用提供的 StringToUTF8()UTF8ToString() 函数来处理您的 string 变量。
【解决方案3】:

使用超对象库,确保使用the latest version from the repository file, not the 1.2.4 ZIP

然后您可以使用.AsJSON(true) 格式化您的 TSuperObject 对象(“t​​rue”可以解决问题)。

[请注意,您无法控制 JSON 字段的显示顺序]

[ 并从字符串创建您的对象:var lJSON : ISuperObject; lJSON := SO(string); ]

【讨论】:

  • 您的建议对我有用,谢谢!刚刚遇到“TSuperObject.ParseString(mystring, true);”的一个小问题其中 mystring 不是字符串类型,而是 PWideString。
【解决方案4】:

这有点老了,但如果有人有兴趣,Delphi 的原生 System.JSON 单元也可以做到这一点。示例使用 TMemo 和 TButton 来格式化 JSON

procedure TForm1.btnFormatJSONClick(Sender: TObject);
const
 DEF_INDENT = 2;
var
 JO : TJSONObject;
begin
 try
  JO := TJSONObject.ParseJSONValue(memoJSON.Text) as TJSONObject;
  memoJSON.Text := JO.Format(DEF_INDENT);
 except
  on E:Exception do
   begin
    MessageDlg('Error in JSON syntax', mtError, [mbOK], 0);
   end;
 end;
end;

【讨论】:

  • TJSONObject.Format 需要 Delphi 10.3 或更新版本
【解决方案5】:

如果您使用 Delphi XE 或更新版本,您可以使用 delphi-xe-json

function PrettyPrint (aJSON : string) : string;
var
  jo : IJSONObject
begin
  jo := TJSON.NewObject(aJSON);
  result := jo.ToString(true);
end;

【讨论】:

  • 是的,也感谢您的建议!我仍然使用 Delphi 7,因为我的项目太大太旧:)
猜你喜欢
  • 2012-10-08
  • 1970-01-01
  • 2010-09-26
  • 2013-10-03
  • 2011-08-05
相关资源
最近更新 更多