JSONValue到缩进字符串

时间:2012-08-03 14:21:07

标签: json delphi indentation stringification jsonlint

在Delphi XE2中,我需要创建一个接收JSONValue并返回缩进String的函数,就像JSONLint一样。这个JSONValue可以是任何类型的JSON,可以是数组,对象,甚至只是一个字符串,所以我必须确保用这个函数覆盖所有类型。我不知道从哪里开始。

3 个答案:

答案 0 :(得分:4)

你必须递归地做。像这样:

const INDENT_SIZE = 2;

procedure PrettyPrintJSON(value: TJSONValue; output: TStrings; indent: integer = 0); forward;

procedure PrettyPrintPair(value: TJSONPair; output: TStrings; last: boolean; indent: integer);
const TEMPLATE = '%s : %s';
var
  line: string;
  newList: TStringList;
begin
  newList := TStringList.Create;
  try
    PrettyPrintJSON(value.JsonValue, newList, indent);
    line := format(TEMPLATE, [value.JsonString.ToString, Trim(newList.Text)]);
  finally
    newList.Free;
  end;

  line := StringOfChar(' ', indent * INDENT_SIZE) + line;
  if not last then
    line := line + ','
  output.add(line);
end;

procedure PrettyPrintJSON(value: TJSONValue; output: TStrings; indent: integer);
var
  i: integer;
begin
  if value is TJSONObject then
  begin
    output.add(StringOfChar(' ', indent * INDENT_SIZE) + '{');
    for i := 0 to TJSONObject(value).size - 1 do
      PrettyPrintPair(TJSONObject(value).Get(i), output, i = TJSONObject(value).size - 1, indent + 1);
    output.add(StringOfChar(' ', indent * INDENT_SIZE) + '}');
  end
  else if value is TJSONArray then
    //left as an exercise to the reader
  else output.add(StringOfChar(' ', indent * INDENT_SIZE) + value.ToString);
end;

这涵盖了基本原则。警告:我把它写在了我的头顶。它可能不正确甚至编译,但它是一般的想法。此外,您必须提出自己的打印JSON数组的实现。但这应该让你开始。

答案 1 :(得分:2)

我采用了梅森的代码,做了读者练习,并把它放在一个单独的单元中:

unit uJSONTools;

interface

Uses
  Classes, SysUtils, DBXJSON;

procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0);
// Formats JSONValue to an indented structure and adds it to OutputStrings

implementation

const INDENT_SIZE = 2;

procedure PrettyPrintPair(JSONValue: TJSONPair; OutputStrings: TStrings; last: boolean; indent: integer);
const TEMPLATE = '%s : %s';
var
  line: string;
  newList: TStringList;
begin
  newList := TStringList.Create;
  try
    PrettyPrintJSON(JSONValue.JsonValue, newList, indent);
    line := format(TEMPLATE, [JSONValue.JsonString.ToString, Trim(newList.Text)]);
  finally
    newList.Free;
  end;

  line := StringOfChar(' ', indent * INDENT_SIZE) + line;
  if not last then
    line := line + ',';
  OutputStrings.add(line);
end;

procedure PrettyPrintArray(JSONValue: TJSONArray; OutputStrings: TStrings; last: boolean; indent: integer);
var i: integer;
begin
   OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '[');
   for i := 0 to JSONValue.size - 1 do
      PrettyPrintJSON(JSONValue.Get(i), OutputStrings, indent + 1);
   OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + ']');
end;

procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0);
var
  i: integer;
begin
  if JSONValue is TJSONObject then
  begin
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '{');
    for i := 0 to TJSONObject(JSONValue).size - 1 do
      PrettyPrintPair(TJSONObject(JSONValue).Get(i), OutputStrings, i = TJSONObject(JSONValue).size - 1, indent + 1);
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '}');
  end
  else if JSONValue is TJSONArray then
    PrettyPrintArray(TJSONArray(JSONValue), OutputStrings, i = TJSONObject(JSONValue).size - 1, indent + 1)
  else OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + JSONValue.ToString);
end;

end.

答案 2 :(得分:1)

为了增加Doggen和Wheeler的答案,我用以下替换替换了PrettyPrintArray例程,以确保数组对象用逗号分隔,否则prettyprint输出是无效的json。

procedure PrettyPrintArray(JSONValue: TJSONArray; OutputStrings: TStrings; last:     boolean; indent: integer);
var i: integer;
begin
   OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '[');
  for i := 0 to JSONValue.size - 1 do
      begin
      PrettyPrintJSON(JSONValue.Get(i), OutputStrings, indent + 1);
      if i < JSONValue.size - 1 then
         OutputStrings[OutputStrings.Count-1] := OutputStrings[OutputStrings.Count-1] + ',';
      end;
   OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + ']');
end;