大家好,
  我写了很久都没写出这个生成树的算法,请帮一下。
function createJsonString(rs:TList):String;
begin
  //这个函数怎么写,才能生成下面的字符串。   [
           {
 'id':'1',
 'txt':'title1',
 'items':[
   {
     'id':'2',
   'txt':'title6'
   },{
     'id':'3',
   'txt':'title4',
               'items':[
    {
     'id':'4',
   'txt':'title5'
    },{
     'id':'5',
   'txt':'title7'
    }
   ]
   }
 ]
  }
          ,{
           'id':'6',
           'txt':'title2'
          }
          ,{
           'id':'7',
           'txt':'title3'
         }
   ]
end;procedure TForm1.Button2Click(Sender: TObject);
var
    f_Record: PFavoritRecord;
    rsList:TList;
    s:String;
begin
    rsList:=TList.Create;
    new(f_Record);
    f_Record.favTitle:='title1';
    f_Record.favIsCat:='1';  //1: 表示是目录
    f_Record.favCat:='';     //‘’表示是根目录
    rsList.add(f_Record);    new(f_Record);
    f_Record.favTitle:='title2';
    f_Record.favIsCat:='';   //'' 表示是节点
    f_Record.favCat:='';     //'' 表示是根结点
    rsList.Add(f_Record);    new(f_Record);
    f_Record.favTitle:='title3';
    f_Record.favIsCat:='';   //'' 节点
    f_Record.favCat:='';     //'' 根结点
    rsList.Add(f_Record);    new(f_Record);
    f_Record.favTitle:='title4';
    f_Record.favIsCat:='1';   //'1' 表示目录
    f_Record.favCat:='title1';     //'title4' 是 'title1's 的子节点,且这个节点也是一个目录
    rsList.Add(f_Record);    new(f_Record);
    f_Record.favTitle:='title5';
    f_Record.favIsCat:='';        //'' 表示节点
    f_Record.favCat:='title4';     //'title5' 是 'title4's 的子节点。
    rsList.Add(f_Record);    new(f_Record);
    f_Record.favTitle:='title6';
    f_Record.favIsCat:='';   // '' 表示节点
    f_Record.favCat:='title1';     //'title6' 是 'title1's 的子节点
    rsList.Add(f_Record);    new(f_Record);
    f_Record.favTitle:='title7';
    f_Record.favIsCat:='';        //'' 表示节点
    f_Record.favCat:='title4';     //'title7' 是 'title4's 的子节点
    rsList.Add(f_Record);    s:= createJsonString(rsList);
end;

解决方案 »

  1.   

    要看你本身  TList的结构。
    写代码太麻烦了
    注意 Json输出的字符串实际上就是javascript中的对象数组。
    你可以先从最简单的写起,先输出最基本的数组,然后数组中嵌套对象,对象中再嵌套数组而已。
      

  2.   

    treeview.savetofile得到的就是一个树形的字符串文本
    再在适当的地方加上{、}即可
      

  3.   

    解决这个问题,需要分两步。
    第一步要解决从List构造正确的结点树。(要确保结点资料正确,父子关系要正确。)
    第二步根据结点树生成字符串。...
        Button1: TButton;
        Memo1: TMemo;
        TV1: TTreeView;
    ...type
      PFavoritRecord=^TFavoritRecord;
      TFavoritRecord=record
        favTitle:string;
        favIsCat:string;
        favCat:string;
    end;function FXTree(tv:TTreeView):string;
    const
      cCRLR=#13#10;
    var
      s:string;  function GSS(ASpaceLen:Integer):string;//Gen Space String:生成空格函数
      var
        i:integer;
      begin
        SetLength(result,ASpaceLen);
        for i:=1 to ASpaceLen do
          result[i]:=' ';
      end;  procedure DFS(ANode:TTreeNode;Level:Integer);
      var
        i,iLevel,iLeft:Integer;
      begin
        if (ANode<>nil) then
        begin
          iLevel:=ANode.Level;
          iLeft:=8*(iLevel+1);
          s:=s+GSS(iLeft)+'{'+cCRLR+
               GSS(iLeft+4)+'''id'':'''+inttostr(ANode.AbsoluteIndex+1)+''','+cCRLR+
               GSS(iLeft+4)+'''txt'':'''+PFavoritRecord(ANode.Data)^.favTitle+'''';      if (ANode.HasChildren) then
          begin
            s:=s+','+cCRLR+GSS(iLeft+4)+
              '''items'':['+cCRLR;
          end
          else begin
            s:=s+cCRLR+GSS(iLeft)+'}';
            if ANode.getNextSibling<>nil then //同级上没有后续结点
              s:=s+',';
            s:=s+cCRLR;
          end;      if ANode.GetNext<>nil then //处理后一个结点与当前结点是否在同一级上
          begin
            Level:=ANode.GetNext.Level;
            Level:=iLevel-Level;
            for i:=0 to Level-1 do //处理后续结点与当前结点相差的级别
            begin
              iLeft:=8*(iLevel-i);
              s:=s+GSS(iLeft+4)+']'+cCRLR+
                   GSS(iLeft)+'}';
              if i=Level-1 then s:=s+',';
              s:=s+cCRLR;
            end;
          end;      DFS(ANode.GetNext,iLevel);
        end;
      end;begin
      if tv.Items.Count=0 then exit;  s:='['+cCRLR;  DFS(tv.Items[0],0);  result:=s+']';
    end;function createJsonString(rs:TList;tv:TTreeView):String;
    var
      sList:TList;
      i,j:integer;
      p:PFavoritRecord;
      node,pnode:TTreeNode;
      sTitle:string;
    begin
      sList:=TList.Create;
      try
        //把目录提取出来
        for i:=rs.Count-1 downto 0 do
        begin
          p:=rs.Items[i];      if p.favIsCat<>'' then //目录
          begin
            sList.Add(p);
            rs.Delete(i);
          end;
        end;    //处理目录
        i:=0;
        while sList.Count>0 do
        begin
          p:=sList.Items[i];      //处理根目录
          if p^.favCat='' then
          begin
            tv.Items.AddObject(nil,p^.favTitle,p);
            sList.Delete(i);
            if i>0 then dec(i);
          end
          else if p^.favCat<>'' then
          begin //一般目录
            //检查在目录树上是否已经查到该目录的父目录
            sTitle:=p^.favCat;
            node:=nil;
            for j:=0 to tv.Items.Count-1 do
              if sTitle=PFavoritRecord(tv.Items[j].Data)^.favTitle then
              begin
                node:=tv.Items[j];
                break;
              end;        if node<>nil then
            begin
              tv.Items.AddChildObject(node,p^.favTitle,p);
              sList.Delete(i);
              if i>0 then dec(i);
            end
            else inc(i);
          end;
        end;    //处理剩下的结点
        for i:=0 to rs.Count-1 do
        begin
          p:=rs.Items[i];      sTitle:=p^.favCat;
          node:=nil;
          for j:=0 to tv.Items.Count-1 do
            if sTitle=PFavoritRecord(tv.Items[j].Data)^.favTitle then
            begin
              node:=tv.Items[j];
              break;
            end;      if node<>nil then
          begin
            //查到该结点下的所有子结点中出现子结点是目录的第一个子结点,
            //主要是为了控制将结点插在目录结点的上面
            pnode:=node.getFirstChild;
            while pnode<>nil do
            begin
              if PFavoritRecord(pnode.Data)^.favIsCat<>'' then break;
              pnode:=pnode.getNextSibling;
            end;        if (pnode<>nil) and (PFavoritRecord(pnode.Data)^.favIsCat<>'') then
              tv.Items.InsertObject(pnode,p^.favTitle,p)
            else
              tv.Items.AddChildObject(node,p^.favTitle,p);
          end
          else tv.Items.AddChildObject(nil,p^.favTitle,p);//顶级结点
        end;    result:=FXTree(tv);
      finally
        sList.Free;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      f_Record: PFavoritRecord;
      rsList:TList;
    begin
      rsList:=TList.Create;  new(f_Record);
      f_Record.favTitle:='title1';
      f_Record.favIsCat:='1';  //1: 表示是目录
      f_Record.favCat:='';     //‘’表示是根目录
      rsList.add(f_Record);  new(f_Record);
      f_Record.favTitle:='title2';
      f_Record.favIsCat:='';   //'' 表示是节点
      f_Record.favCat:='';     //'' 表示是根结点
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title3';
      f_Record.favIsCat:='';   //'' 节点
      f_Record.favCat:='';     //'' 根结点
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title4';
      f_Record.favIsCat:='1';   //'1' 表示目录
      f_Record.favCat:='title1';     //'title4' 是 'title1's 的子节点,且这个节点也是一个目录
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title5';
      f_Record.favIsCat:='';        //'' 表示节点
      f_Record.favCat:='title4';     //'title5' 是 'title4's 的子节点。
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title6';
      f_Record.favIsCat:='';   // '' 表示节点
      f_Record.favCat:='title1';     //'title6' 是 'title1's 的子节点
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title7';
      f_Record.favIsCat:='';        //'' 表示节点
      f_Record.favCat:='title4';     //'title7' 是 'title4's 的子节点
      rsList.Add(f_Record);  {new(f_Record);
      f_Record.favTitle:='title8';
      f_Record.favIsCat:='1';        //'' 表示目录
      f_Record.favCat:='title1';     //'title8' 是 'title1's 的子节点
      rsList.Add(f_Record);  new(f_Record);
      f_Record.favTitle:='title9';
      f_Record.favIsCat:='';        //'' 表示节点
      f_Record.favCat:='title8';     //'title9' 是 'title8's 的子节点
      rsList.Add(f_Record);}  TV1.Items.Clear;
      Memo1.Text:= createJsonString(rsList,TV1);
      rsList.Free;
    end;