Last Updated:

Parsing JSON Ke TTreeView

Grup KPPDI
Grup KPPDI Delphi

Misalkan kita punya aplikasi yang memuat JSON dari REST Endpoint, dan kita ingin menampilkannya ke treeview, maka contoh berikut ini dapat digunakan sebagai langkah awal untuk melakukan parsing. Mari kita ikuti langkah-langkahnya:

Siapkan satu buah form, pada form tersebut tambahkan satu buah panel, satu buah treeview buah dan satu buah memo. Pada panel tambahkan satu buah tombol, dan atur posisi komponen-komponen tersebut seperti contoh gambar berikut:

Kemudian, sebelum coding, perlu disiapkan library yang dibutuhkan, yaitu SuperObject, yang merupakan JSON library favorit saya. Library ini sudah disiapkan bersama source code contoh aplikasi ini.

 

Untuk menggunakan library tersebut, tambahkan SuperObject.pas ke project:

Dan pilih SuperObject.pas

Kemudian tambahkan SuperObject ke klausa uses:

 

Property Text dari Memo1 dapat diganti dengan default JSON text, misalnya:

{
  "id": "0001",
  "type": "donut",
  "name": "Cake",
  "ppu": 0.55,
  "batters":
    {
      "batter":
        [
          { "id": "1001", "type": "Regular" },
          { "id": "1002", "type": "Chocolate" },
          { "id": "1003", "type": "Blueberry" },
          { "id": "1004", "type": "Devil's Food" }
        ]
    },
  "topping":
    [
      { "id": "5001", "type": "None" },
      { "id": "5002", "type": "Glazed" },
      { "id": "5005", "type": "Sugar" },
      { "id": "5007", "type": "Powdered Sugar" },
      { "id": "5006", "type": "Chocolate with Sprinkles" },
      { "id": "5003", "type": "Chocolate" },
      { "id": "5004", "type": "Maple" }
    ]
}

 

Klik ganda pada tombol caption Parse, kemudian isikan kode seperti berikut:

var
  s, v: string;
  curv,
  iso: ISuperObject;
  item: TSuperObjectIter;
  tvi: TTreeNode;
begin
  s := Memo1.Text;
  TreeView1.Items.BeginUpdate;
  try
    TreeView1.Items.Clear;
    tvi := TreeView1.Items.AddFirst(nil, 'Parsed Data:');
    if (s = '') or (s = '{}') then
    begin
      TreeView1.Items.AddChild(tvi, 'Tidak ada data...');
    end
    else
    begin
      iso := so(s);
      ParseItemsIntoTreeView(tvi, iso);
    end;
  finally
    TreeView1.Items.EndUpdate;
    TreeView1.Items[0].Expand(false);
    TreeView1.Items[0].MakeVisible;
  end;
end;

Kode di atas membuat node pertama bernama tvi dengan caption "Parsed Data:" jika teks pada Memo1 tidak kosong. Teks kemudian diparse ke JSON object pada variabel iso:

iso := so(s);

Lalu JSON ini ditelusuri item-itemnya dan dimuat ke treeview dengan menginduk ke node pertama, yaitu tvi

ParseItemsIntoTreeView(tvi, iso);

Berikut fungsi parse JSON ke treeview:

procedure TForm1.ParseItemsIntoTreeView(
  node: TTreeNode; itemData: ISuperObject);
var
  curv: ISuperObject;
  cura: TSuperArray;
  item: TSuperObjectIter;
  tvi: TTreeNode;
  s, v, dv: string;
  i: integer;
begin
  try
    if ObjectFindFirst(itemData, item) then
    repeat
      s := item.key;
      v := '';
      if item.val.IsType(stString) then
      begin
        v := item.val.AsString;
        dv := copy(v,1,10);
        // '2020-06-04'
        if
          (length(dv)>=10) and
          (dv[5] = '-') and (dv[8] = '-') and
          (_s(_i( copy(dv,1,4) ,0)) = copy(dv,1,4)) and
          (_s(_i( copy(dv,6,2) ,0),2) = copy(dv,6,2)) and
          (_s(_i( copy(dv,9,2) ,0),2) = copy(dv,9,2))
        then
        begin
          TreeView1.Items.AddChild(
            node,
            s+': '+DateIndoShort(DateFromSQL(dv))+' '+
              copy(v,11,length(v))
          )

        end
        else
          TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stBoolean) then
      begin
        v := BoolToStr(item.val.AsBoolean, true);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stInt) then
      begin
        v := FloatToStr( item.val.AsInteger);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stDouble) then
      begin
        v := FloatToStr( item.val.AsDouble);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stCurrency) then
      begin
        v := FloatToStr (item.val.AsCurrency);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stNull) then
      begin
        v := '';
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stObject) then
      begin
        v := item.val.AsString();
        tvi := TreeView1.Items.AddChild(node, s+':');
        ParseItemsIntoTreeView(tvi, item.val);
      end
      else
      if item.val.IsType(stArray) then
      begin
        v := item.val.AsString();
        cura := item.val.AsArray;
        tvi := TreeView1.Items.AddChild(node, s+':');
        for i := 0 to cura.Length-1 do
        begin
          ParseItemsIntoTreeView(
            TreeView1.Items.AddChild(tvi, _s(i+1)+'.:'),
            cura[i]
          );
        end;
      end;
    until not ObjectFindNext(item);
  finally

  end;
end;

 

 

Beberapa fungsi bantu dapat Anda lihat pada listing lengkap berikut:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Vcl.ExtCtrls, Vcl.ComCtrls, SuperObject;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    TreeView1: TTreeView;
    Panel1: TPanel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure ParseItemsIntoTreeView(node: TTreeNode; itemData: ISuperObject);
    function _s(i: integer; padLeftWith0Count: integer = 0): string;
    function _i(s: String; default: integer = 0): Integer;
    function  DateFromSQL(const ASQLDate: String): TDateTime;
    function  DateIndoShort (const ADate: TDate):String;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
var
  s, v: string;
  curv,
  iso: ISuperObject;
  item: TSuperObjectIter;
  tvi: TTreeNode;
begin
  s := Memo1.Text;
  TreeView1.Items.BeginUpdate;
  try
    TreeView1.Items.Clear;
    tvi := TreeView1.Items.AddFirst(nil, 'Parsed Data:');
    tvi.ImageIndex := 0;
    if (s = '') or (s = '{}') then
    begin
      TreeView1.Items.AddChild(tvi, 'Tidak ada data...').ImageIndex := 5;
    end
    else
    begin
      iso := so(s);
      ParseItemsIntoTreeView(tvi, iso);
    end;
  finally
    TreeView1.Items.EndUpdate;
    TreeView1.Items[0].Expand(false);
    TreeView1.Items[0].MakeVisible;
  end;
end;

function TForm1.DateFromSQL(const ASQLDate: String): TDateTime;
begin
  try
    Result := EncodeDate(
      _i(Copy(ASQLDate,1,4)),
      _i(Copy(ASQLDate,6,2)),
      _i(Copy(ASQLDate,9,2))
    );
  except
    Result := Date();
  end;
end;

function TForm1.DateIndoShort(const ADate: TDate): String;
begin
  Result := FormatDateTime('dd/MM/yyyy', ADate);
end;

procedure TForm1.ParseItemsIntoTreeView(
  node: TTreeNode; itemData: ISuperObject);
var
  curv: ISuperObject;
  cura: TSuperArray;
  item: TSuperObjectIter;
  tvi: TTreeNode;
  s, v, dv: string;
  i: integer;
begin
  try
    if ObjectFindFirst(itemData, item) then
    repeat
      s := item.key;
      v := '';
      if item.val.IsType(stString) then
      begin
        v := item.val.AsString;
        dv := copy(v,1,10);
        // '2020-06-04'
        if
          (length(dv)>=10) and
          (dv[5] = '-') and (dv[8] = '-') and
          (_s(_i( copy(dv,1,4) ,0)) = copy(dv,1,4)) and
          (_s(_i( copy(dv,6,2) ,0),2) = copy(dv,6,2)) and
          (_s(_i( copy(dv,9,2) ,0),2) = copy(dv,9,2))
        then
        begin
          TreeView1.Items.AddChild(
            node,
            s+': '+DateIndoShort(DateFromSQL(dv))+' '+
              copy(v,11,length(v))
          )

        end
        else
          TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stBoolean) then
      begin
        v := BoolToStr(item.val.AsBoolean, true);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stInt) then
      begin
        v := FloatToStr( item.val.AsInteger);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stDouble) then
      begin
        v := FloatToStr( item.val.AsDouble);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stCurrency) then
      begin
        v := FloatToStr (item.val.AsCurrency);
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stNull) then
      begin
        v := '';
        TreeView1.Items.AddChild(node, s+': '+v)
      end
      else
      if item.val.IsType(stObject) then
      begin
        v := item.val.AsString();
        tvi := TreeView1.Items.AddChild(node, s+':');
        ParseItemsIntoTreeView(tvi, item.val);
      end
      else
      if item.val.IsType(stArray) then
      begin
        v := item.val.AsString();
        cura := item.val.AsArray;
        tvi := TreeView1.Items.AddChild(node, s+':');
        for i := 0 to cura.Length-1 do
        begin
          ParseItemsIntoTreeView(
            TreeView1.Items.AddChild(tvi, _s(i+1)+'.:'),
            cura[i]
          );
        end;
      end;
    until not ObjectFindNext(item);
  finally

  end;
end;

function TForm1._i(s: String; default: integer = 0): Integer;
begin
  Result := StrToIntDef(s, default);
end;

function TForm1._s(i: integer; padLeftWith0Count: integer = 0): string;
begin
  Result := IntToStr(i);
  if padLeftWith0Count> 0 then
  begin
    while length(Result)<padLeftWith0Count do
      Result := '0' + Result;
  end;
end;

end.

 

Source code dapat diunduh di
https://github.com/kppdi/ParseJSONToTreeView

Comments