JSONValue в строку с отступом

В Delphi XE2 мне нужно создать функцию, которая получает JSONValue и возвращает String с отступом, как JSONLint. Это JSONValue может быть любым типом JSON, может быть массивом, объектом, даже просто строкой, поэтому я должен убедиться, что эта функция охватывает все типы. Я понятия не имею, с чего начать.


person bpromas    schedule 03.08.2012    source источник
comment
вы хотите красиво печатать строки json?   -  person Marc B    schedule 03.08.2012


Ответы (3)


Вам придется делать это рекурсивно. Что-то вроде этого:

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. Но это должно заставить вас начать.

person Mason Wheeler    schedule 03.08.2012

Я взял код у Мейсона, сделал упражнение для читателей и поместил его в отдельный блок:

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.
person Jan Doggen    schedule 30.08.2012
comment
В коде отсутствуют запятые между объектами в массиве. - person rhody; 08.08.2014

Чтобы дополнить ответ Доггена и Уиллера, я заменил подпрограмму 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;
person rhody    schedule 07.08.2014