修改SuperObject以格式化/缩进JSON字符串的方式不同?

时间:2014-08-19 01:01:28

标签: json delphi serialization formatting superobject

使用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库以使其格式化不同?库中是否有特定的位置来定义这些格式规则?或者我是否需要深入研究许多不同地方的代码来改变它?

1 个答案:

答案 0 :(得分: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
}