创建树结构的JSON

时间:2017-01-17 12:32:12

标签: json delphi recursion

我有一个TDepartment类型的对象列表,看起来像这样

TDepartment = class
  ID : Integer;
  Name : string;
  ParentDepartmentID : Integer;
end;

我需要创建一个TJSONObject,其中包含一系列部门,所有部门都可以拥有一系列部门。所以深度不明。

我现在正处于一个对我来说根本没有意义的地方,但我希望生成的JSON看起来像这样:

    "department_id": "5",
    "department_name": "100",
    "parent_dept_id": "",
    "subdepartments": [{
        "department_id": "8",
        "department_name": "300",
        "parent_dept_id": "5",
        "subdepartments": [{
            "department_id": "1",
            "department_name": "310",
            "parent_dept_id": "8",
            "subdepartments": []

请记住,每个级别都有未知数量的兄弟姐妹和孩子。 我想我需要编写一个递归过程,但我无法将其可视化。

2 个答案:

答案 0 :(得分:1)

首先,您可能希望您的TDepartment声明与您描述的嵌套结构相匹配:

TDepartment = class
  ID : Integer;
  Name : string;
  ParentDepartmentID : Integer;
  SubDepartments: array of TDepartment;
end;

为了序列化这个,我建议使用SuperObject库而不是内置的JSON类:

function TDepartment.Serialize: ISuperObject;
  var Context: TSuperRttiContext;
begin
  Context := TSuperRttiContext.Create;
  try
    Result := Context.AsJson<TDepartment>(self);
  finally
    Context.Free;
  end;
end;

在评论中,OP提到TDepartment包含更多字段,但只有问题中的字段应序列化;还必须使用TJSONObject,并且部门不了解其子女。你可以这样做:

function TDepartment.Serialize2(AllDepartments: TList<TDepartment>): TJSONObject;
  var Department: TDepartment;
      Subdepartments: TJSONArray;
begin
  Result := TJSONObject.Create;
  Result.AddPair(TJSONPair.Create('department_id', TJSONNumber.Create(ID)));
  Result.AddPair(TJSONPair.Create('department_name', Name));
  Result.AddPair(TJSONPair.Create('parent_dept_id', TJSONNumber.Create(ParentDepartmentID)));

  Subdepartments := TJSonArray.Create;
  for Department in AllDepartments do
  begin
    if (Department.ParentDepartmentID <> ID) then Continue;
    Subdepartments.AddElement(Department.Serialize2(AllDepartments));
  end;
  Result.AddPair(TJSONPair.Create('subdepartments', Subdepartments));
end;

答案 1 :(得分:0)

我会创建一个并行树结构,保留原始原样。您当前的结构将根据您的需要进行反转,因此您可以扫描当前对象,将它们放在树中。但是在不知道当前结构的情况下,这很难给出示例代码,但是假设所有部门都存在于某种列表中(让我们称之为“部门”)和“根部”#39;部门的父部门ID为零,它会是这样的:

unit Unit1;

interface

uses
  System.Generics.Collections;

type
  TDepartment = class
    ID : Integer;
    Name : string;
    ParentDepartmentID : Integer;
  end;

  TDepartmentStructure = class
    ID : Integer;
    Name : string;
    ParentDepartmentID : Integer;
    SubDepartments: TList< TDepartmentStructure >;
    constructor Create( const pBasedOn : TDepartment );
  end;

var
  Department : TObjectList<TDepartment>;

function CopyStructure( pDepartment : TList<TDepartment> ) : TDepartmentStructure; // returns root

implementation

var
  DepartmentStructure : TObjectList<TDepartmentStructure>;

function CopyStructure( pDepartment : TList<TDepartment> ) : TDepartmentStructure;
var
  i, j: Integer;
begin
  // stage one - copy everything
  for i := 0 to pDepartment.Count - 1 do
  begin
    DepartmentStructure.Add( TDepartmentStructure.Create( pDepartment[ i ] ));
  end;
  // now go through and build structure
  Result := nil;
  for i := 0 to DepartmentStructure.Count - 1 do
  begin
    if DepartmentStructure[ i ].ID = 0 then
    begin
      // root
      Result := DepartmentStructure[ i ];
    end
    else
    begin
      for j := 0 to DepartmentStructure.Count - 1 do
      begin
        if DepartmentStructure[ i ].ParentDepartmentID = DepartmentStructure[ j ].ID then
        begin
          DepartmentStructure[ j ].SubDepartments.Add( DepartmentStructure[ i ] );
          break;
        end;
      end;
    end;
  end;
end;

{ TDepartmentStructure }

constructor TDepartmentStructure.Create(const pBasedOn: TDepartment);
begin
  inherited Create;
  ID := pBasedOn.ID;
  Name := pBasedOn.Name;
  ParentDepartmentID := pBasedOn.ParentDepartmentID;
  SubDepartments:= TObjectList< TDepartmentStructure >.Create( FALSE ); // we do NOT own these objects!

end;

initialization
  DepartmentStructure := TObjectList<TDepartmentStructure>.Create( TRUE );

finalization
  DepartmentStructure.Free;

end.

请注意,这仅用于说明目的。您可能不会创建和销毁我所拥有的结构。拥有该结构后,您无疑可以使用当前例程创建JSON记录。

相关问题