3

使用该SuperObject库时,单个 JSON 对象当前缩进如下:

{
 "name": "value",
 "int_arr": [
  1,2,3],
 "obj_arr": [
  {
   "this": "that"
  },{
   "some": "thing"
  }],
 "another": 123
}

但是,这种缩进/格式与 JSON 大肆宣传的“用户友好”或“人类可读”不同。我理解计算机语言,这并不重要,但我想像这样格式化它:

{
  "name": "value",
  "int_arr": [1,2,3],
  "obj_arr": [
    {
      "this": "that"
    },
    {
      "some": "thing"
    }
  ],
  "another": 123
} 

例如,当使用JSONLint验证/格式化 JSON 代码时,它会以更简洁的方式进行。

我怎样才能去修改SuperObject库以不同的格式?库中是否有定义这些格式规则的特定位置?或者我是否必须深入研究许多不同地方的代码才能改变这一点?

4

1 回答 1

3

感谢评论David A,实现这些更改相当简单(在格式化源代码并了解库的代码如何工作之后)。所有格式都在 中实现TSuperObject.Write,所有这些更改都可以在此处进行。

只有一个问题我无法弄清楚,那就是对象以外的类型数组 - 值将转到下一行。但至少数组结尾和对象数组具有所需的换行符和缩进。

这是下面的修改版本TSuperObject.Write(大多数子程序不包括在内以节省空间)。更改评论:

持续的:

const
  TOK_SP: PSOChar = #32#32; //<-- added another #32

子程序:

  procedure _indent(I: shortint; r: boolean);
  begin
    Inc(level, I);
    if r then
      with writer do
      begin
{$IFDEF MSWINDOWS}
        Append(TOK_CRLF, 2);
{$ELSE}
        Append(TOK_LF, 1);
{$ENDIF}
        for I := 0 to level - 1 do
          Append(TOK_SP, 2); //<-- changed 1 to 2
      end;
  end;

程序主体:

begin

  if FProcessing then
  begin
    Result := writer.Append(TOK_NULL, 4);
    Exit;
  end;

  FProcessing := true;
  with writer do
    try
      case FDataType of
        stObject:
          if FO.c_object.FCount > 0 then
          begin
            k := 0;
            Append(TOK_CBL, 1);
            if indent then
              _indent(1, false);
            if ObjectFindFirst(Self, iter) then
              repeat
{$IFDEF SUPER_METHOD}
                if (iter.val = nil) or not ObjectIsType(iter.val, stMethod) then
                begin
{$ENDIF}
                  if (iter.val = nil) or (not iter.val.Processing) then
                  begin
                    if (k <> 0) then
                      Append(TOK_COM, 1);
                    if indent then
                      _indent(0, true);
                    Append(TOK_DQT, 1);
                    if escape then
                      DoEscape(PSOChar(iter.key), Length(iter.key))
                    else
                      DoMinimalEscape(PSOChar(iter.key), Length(iter.key));
                    if indent then
                      Append(ENDSTR_A, 3)
                    else
                      Append(ENDSTR_B, 2);
                    if (iter.val = nil) then
                      Append(TOK_NULL, 4)
                    else
                      iter.val.Write(writer, indent, escape, level);
                    Inc(k);
                  end;
{$IFDEF SUPER_METHOD}
                end;
{$ENDIF}
              until not ObjectFindNext(iter);
            ObjectFindClose(iter);
            if indent then
              _indent(-1, true);
            Result := Append(TOK_CBR, 1);
          end
          else
            Result := Append(TOK_OBJ, 2);
        stBoolean:
          begin
            if (FO.c_boolean) then
              Result := Append(TOK_TRUE, 4)
            else
              Result := Append(TOK_FALSE, 5);
          end;
        stInt:
          begin
            str(FO.c_int, st);
            Result := Append(PSOChar(SOString(st)));
          end;
        stDouble:
          Result := Append(PSOChar(SOString(gcvt(FO.c_double, 15, fbuffer))));
        stCurrency:
          begin
            Result := Append(PSOChar(CurrToStr(FO.c_currency)));
          end;
        stString:
          begin
            Append(TOK_DQT, 1);
            if escape then
              DoEscape(PSOChar(FOString), Length(FOString))
            else
              DoMinimalEscape(PSOChar(FOString), Length(FOString));
            Append(TOK_DQT, 1);
            Result := 0;
          end;
        stArray:
          if FO.c_array.FLength > 0 then
          begin
            Append(TOK_ARL, 1);
            if indent then
              _indent(1, true);
            k := 0;
            j := 0;
            while k < FO.c_array.FLength do
            begin

              val := FO.c_array.GetO(k);
{$IFDEF SUPER_METHOD}
              if not ObjectIsType(val, stMethod) then
              begin
{$ENDIF}
                if (val = nil) or (not val.Processing) then
                begin
                  if (j <> 0) then begin
                    Append(TOK_COM, 1);
                    if ObjectIsType(val, stObject) then begin //
                      if indent then                          //<-- create line break after object array items
                        _indent(0, true);                     //
                    end;                                      //
                  end;
                  if (val = nil) then
                    Append(TOK_NULL, 4)
                  else
                    val.Write(writer, indent, escape, level);
                  Inc(j);
                end;
{$IFDEF SUPER_METHOD}
              end;
{$ENDIF}
              Inc(k);
            end;
            if indent then
              _indent(-1, true); //<-- changed "false" to "true" to create line break at end of array
            Result := Append(TOK_ARR, 1);
          end
          else
            Result := Append(TOK_ARRAY, 2);
        stNull:
          Result := Append(TOK_NULL, 4);
      else
        Result := 0;
      end;
    finally
      FProcessing := false;
    end;
end;

该代码将生成 JSON 数据,如下所示:

{
  "name": "value",
  "int_arr": [
    1,2,3
  ],
  "obj_arr": [
    {
      "this": "that"
    },
    {
      "some": "thing"
    }
  ],
  "another": 123
} 
于 2014-08-19T04:58:50.520 回答