關於內存數據與 JSON,內存數據JSON
閒話:
正在用 WebBroker 寫一個小網站,感受頗多:
1、如果是寫一個小東西,應該先考慮下 WebBroker,因為它是分分鐘即可上手的。
2、如果要寫一個大東西,或許也應該考慮下 WebBroker,因為相比其他它有著最高的靈活度(但這只是相像,因為我只是寫了一個小東西)。
3、Delphi 3 就有了 WebBroker,可惜現在才開始使用它;隨著“服務器”與“網頁程序”的普及,WebBroker 應該會被更多地提起。
期間用到了 json, 所以有了這篇博文。
Delphi 與內存數據的總結與回顧:
1、普通變量:儲存一個數據。
2、數組:儲存一組同類型的數據。
3、結構體:儲存一組不同類型的數據;現在的結構體越來越復雜了,還可以操作這些個數據,越來越像“類”了。
4、“鍵值”對:我一般使用 TStringList,並常常用它代替 ini 文件類;同類還有 THashedStringList、TStringHash。
5、分類的 “鍵值”對:TMemIniFile、TIniFile; 另外還有人用 sqlite 做了一個可以儲存二進制數據的 ini 文件類(忘了名了),我試過,非常好用(在官方示例中)。
6、內存數據表:現在應該首選 TFDMemTable 了(之前是 TClientDataSet)。
7、數據庫級別的內存(或文件)數據:SqLite。
8、內存多叉樹:JSON;之前一直使用 SuperObject,以後會使用 System.JSON 更多些。
System.JSON?還是 SuperObject?
System.JSON 是官方的;這省去很多麻煩,這也是我考慮它的主要原因。
System.JSON 沒有提供 “修改”、“讀寫文件” 與 “格式化” 的功能,盡管可以變通實現,但怎麼都不如 SuperObject 方便。
System.JSON 主要考慮的是:從服務器生成 json,然後傳輸到客戶端(特別是給 JavaScript 使用),不像 SuperObject 大而全。
如果只用到 “寫入” 和 “讀取”,優先考慮 System.JSON 吧;如果需要更多功能,SuperObject 會更理想。
1 分鐘了解 System.JSON:
其中的類不少,主要用到的有:TJSONObject、TJSONArray。
uses System.JSON;
//TJSONObject
procedure TForm1.Button1Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;
j.AddPair('aa', '111');
j.AddPair('bb', '222');
//輸出字符串
Memo1.Text := j.ToString; //結果:{"aa":"111","bb":"222"}
{ToJSON 與 ToString 結果相同,但應盡量使用 ToString 而不是 ToJSON;因為 ToJSON 也是調用 ToString 並且還要重新分配內存}
j.Free;
end;
//TJSONArray
procedure TForm1.Button2Click(Sender: TObject);
var
a: TJSONArray;
begin
a := TJSONArray.Create;
a.Add(1);
a.Add(2);
a.Add('aaa');
a.Add('bbb');
Memo1.Text := a.ToString; //結果:[1,2,"aaa","bbb"]
a.Free;
end;
//當 TJSONObject 嵌套其他對象時
procedure TForm1.Button3Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;
a := TJSONArray.Create('aaa', 'bbb'); //可以使用兩個值初始化
a.Add(1);
a.Add(2);
j.AddPair('arr', a);
Memo1.Text := j.ToString; //結果:{"arr":["aaa","bbb",1,2]}
// a.Free; {千萬不要釋放其內部對象,它的父對象會自動釋放它}
j.Free;
end;
//變通上例
procedure TForm1.Button4Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;
j.AddPair('arr', TJSONArray.Create);
with j.Values['arr'] as TJSONArray do
begin
Add('aaa');
Add('bbb');
Add(1);
Add(2);
end;
Memo1.Text := j.ToString; //結果:{"arr":["aaa","bbb",1,2]}
j.Free;
end;
//再變通
procedure TForm1.Button5Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;
j.AddPair('arr', TJSONArray.Create);
a := TJSONArray(j.Values['arr']);
a.Add('aaa');
a.Add('bbb');
a.Add(1);
a.Add(2);
Memo1.Text := j.ToString; //結果:{"arr":["aaa","bbb",1,2]}
j.Free;
end;
//添加其他類型的數
procedure TForm1.Button6Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;
j.AddPair('數值', TJSONNumber.Create(3.1415926));
j.AddPair('布爾真', TJSONTrue.Create);
j.AddPair('布爾假', TJSONFalse.Create);
j.AddPair('空值', TJSONNull.Create);
Memo1.Text := j.ToString; //結果:{"數值":3.1415926,"布爾真":true,"布爾假":false,"空值":null}
j.Free;
end;
//讀取
procedure TForm1.Button7Click(Sender: TObject);
var
j: TJSONObject;
str: string;
num: Integer;
arr1,arr2: string;
begin
j := TJSONObject.Create;
j.AddPair('str', '111');
j.AddPair('num', TJSONNumber.Create(222));
j.AddPair('arr', TJSONArray.Create('arr1', 'arr2'));
Memo1.Text := j.ToString; //結果:{"str":"111","num":222,"arr":["arr1","arr2"]}
//JSON 是一組”鍵值對“,其中的”值“還有可能是”鍵值對“;
//所以 System.JSON 用 TJSONValue 來表示值類型,它是所有值類型的父類,當然也是 TJSONObject 的父類。
str := j.Values['str'].Value; //Values[] 調用的是 GetValue(), 更喜歡直接用後者
num := j.GetValue('num').Value.ToInteger;
arr1 := TJSONArray(j.GetValue('arr')).Items[0].Value;
arr2 := TJSONArray(j.GetValue('arr')).Items[1].Value;
Memo1.Lines.Add(Format('%s, %d, %s, %s', [str, num, arr1, arr2])); //111, 222, arr1, arr2
j.Free;
end;
//遍歷
procedure TForm1.Button8Click(Sender: TObject);
var
j: TJSONObject;
p: TJSONPair;
v: TJSONValue;
i: Integer;
a: TJSONArray;
begin
j := TJSONObject.Create;
j.AddPair('aa', '111');
j.AddPair('bb', '222');
j.AddPair('arr', TJSONArray.Create('arr1', 'arr2'));
//集合遍歷 TJSONObject
for p in j do
Memo1.Lines.Add(p.ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"]
//索引遍歷 TJSONObject, 這裡的 Get 函數已不提倡使用了
for i := 0 to j.Count - 1 do
Memo1.Lines.Add(j.Get(i).ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"]
//集合遍歷 TJSONArray
for v in j.Values['arr'] as TJSONArray do
Memo1.Lines.Add(v.Value); //arr1 \\ arr2
//索引遍歷 TJSONArray
a := j.Values['arr'] as TJSONArray;
for i := 0 to a.Count - 1 do
Memo1.Lines.Add(a.Items[i].Value); //arr1 \\ arr2
end;
//存取到文件
procedure TForm1.Button9Click(Sender: TObject);
var
j1,j2: TJSONObject;
begin
//隨便虛擬些數據
j1 := TJSONObject.Create(TJSONPair.Create('aaa', '111'));
j1.AddPair('bbb', j1.Clone as TJSONValue);
ChDir('c:\temp');
//寫入文件
with TStringList.Create do
begin
Add(j1.ToString);
SaveToFile('JsonTest.txt', TEncoding.UTF8); //結果:{"aaa":"111","bbb":{"aaa":"111"}}
Free;
end;
j1.Free;
//從文件讀取
with TStringList.Create do
begin
LoadFromFile('JsonTest.txt', TEncoding.UTF8);
j2 := TJSONObject.ParseJSONValue(Text) as TJSONObject;
Free;
end;
Memo1.Text := j2.ToString; //結果:{"aaa":"111","bbb":{"aaa":"111"}}
j2.Free;
end;
//假如非要修改數據
procedure TForm1.Button10Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;
j.AddPair('aaa', '111');
j.AddPair('bbb', '222');
Memo1.Text := j.ToString; //結果:{"aaa":"111","bbb":"222"}
//所謂修改,在這裡只能是先刪除再添加
j.RemovePair('aaa');
j.AddPair('aaa', '333');
Memo1.Lines.Add(j.ToString); //結果:{"bbb":"222","aaa":"333"}
j.Free;
end;