
Parsing JSON Ke TTreeView
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