About memory data and JSON

I am using WebBroker to write a small website, and I feel a lot:
1. If you are writing a small thing, you should consider WebBroker first, because it can be started in minutes.
2. If you want to write a big thing, perhaps you should also consider WebBroker, because it has the highest flexibility compared to other things (but this is just imagination, because I only wrote a small thing).
3. Delphi 3 has WebBroker, but it is only now starting to use it; with the popularity of “server” and “web application”, WebBroker should be mentioned more.
Summary and review of Delphi and memory data:
1. Common variable: store a data.
2. Array: store a group of data of the same type.
3. Structure: Store a set of different types of data; now the structure is getting more and more complicated, and you can also manipulate these data, which is more and more like a “class”.
4. “Key-value” pair: I generally use TStringList, and often use it instead of ini file class; there are THashedStringList, TStringHash in the same category.
5. Classification of “key-value” pairs: TMemIniFile, TIniFile; In addition, someone has used sqlite to make an ini file class that can store binary data (forgot the name), I tried it, and it works very well (in the official example) .
6. Memory data table: TFDMemTable should now be the first choice (previously TClientDataSet).
7. Memory (or file) data at database level: SqLite.
8. Memory polytree: JSON (or XML); SuperObject has been used before, and System.JSON will be used more in the future.
System.JSON? Or SuperObject?
System.JSON is official; this saves a lot of trouble, which is the main reason I consider it.
System.JSON “read and write files” and “format” functions, both of which are not as convenient as SuperObject.
The main consideration of System.JSON is: generate json from the server and then transmit it to the client (especially for JavaScript use), unlike SuperObject.
If it is not too complicated json application, give priority to System.JSON; if you need more features, SuperObject will be more ideal.
Learn about System.JSON in 1 minute:
There are many classes, mainly used: TJSONObject, TJSONArray.
ses System.JSON; //TJSONObject procedure TForm1.Button1Click(Sender: TObject); var j: TJSONObject; begin j := TJSONObject.Create; j.AddPair('aa', '111'); j.AddPair('bb', '222'); //Output string Memo1.Text := j.ToString; //result:{"aa":"111","bb":"222"} {ToJSON and ToString have the same result, but you should try to use ToString instead of ToJSON; because ToJSON also calls ToString and needs to reallocate memory} j.Free; end; //TJSONArray procedure TForm1.Button2Click(Sender: TObject); var a: TJSONArray; begin a := TJSONArray.Create; a.Add(1); //TJSONArray is not like a traditional array, it can accept several different types of values; this should be regarded as an extension of the Delphi array function. a.Add(2); a.Add('aaa'); a.Add('bbb'); Memo1.Text := a.ToString; //result:[1,2,"aaa","bbb"] a.Free; end; //When TJSONObject nests other objects procedure TForm1.Button3Click(Sender: TObject); var j: TJSONObject; a: TJSONArray; begin j := TJSONObject.Create; a := TJSONArray.Create('aaa', 'bbb'); //Can be initialized with two values a.Add(1); a.Add(2); j.AddPair('arr', a); Memo1.Text := j.ToString; //result:{"arr":["aaa","bbb",1,2]} // a.Free; {Never release its internal object, its parent object will automatically release it} j.Free; end; //Work around the example 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; //result:{"arr":["aaa","bbb",1,2]} j.Free; end; //Adapt again 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; //result:{"arr":["aaa","bbb",1,2]} j.Free; end; //Add other types of numbers 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; //Result: {"Value":3.1415926,"Boolean True":true,"Boolean False":false,"Null Value":null} j.Free; end; //Read 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; //result:{"str":"111","num":222,"arr":["arr1","arr2"]} //JSON is a set of "key-value pairs", where the "value" may also be a "key-value pair"; //So System.JSON uses TJSONValue to represent the value type, which is the parent class of all value types, and of course it is also the parent class of TJSONObject. str := j.Values['str'].Value; //Values[] calls GetValue(), prefer to use the latter directly 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; //Traverse 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')); //Collection traversal TJSONObject for p in j do Memo1.Lines.Add(p.ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"] //Index traverses TJSONObject, the Get function here is no longer recommended for i := 0 to j.Count - 1 do Memo1.Lines.Add(j.Get(i).ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"] //Collection traversal TJSONArray for v in j.Values['arr'] as TJSONArray do Memo1.Lines.Add(v.Value); //arr1 \\ arr2 //Index traversal TJSONArray a := j.Values['arr'] as TJSONArray; for i := 0 to a.Count - 1 do Memo1.Lines.Add(a.Items[i].Value); //arr1 \\ arr2 j.Free; end; //Access to file procedure TForm1.Button9Click(Sender: TObject); var j1,j2: TJSONObject; begin //Just dummy data j1 := TJSONObject.Create(TJSONPair.Create('aaa', '111')); j1.AddPair('bbb', j1.Clone as TJSONValue); ChDir('c:\temp'); //Write file with TStringList.Create do begin Add(j1.ToString); SaveToFile('JsonTest.txt', TEncoding.UTF8); //ressult:{"aaa":"111","bbb":{"aaa":"111"}} Free; end; j1.Free; //Read from file with TStringList.Create do begin LoadFromFile('JsonTest.txt', TEncoding.UTF8); j2 := TJSONObject.ParseJSONValue(Text) as TJSONObject; Free; end; Memo1.Text := j2.ToString; //result:{"aaa":"111","bbb":{"aaa":"111"}} j2.Free; end; //Modify, delete procedure TForm1.Button10Click(Sender: TObject); var j: TJSONObject; begin j := TJSONObject.Create; j.AddPair('aaa', '111'); j.AddPair('bbb', '222'); j.AddPair('ccc', '333'); //modify j.Get('aaa').JsonValue := TJSONString.Create('11111'); //JsonString and JsonValue of TJSONPair are key and value respectively // j.Pairs[0].JsonValue := TJSONString.Create('11111'); //delete j.RemovePair('bbb'); Memo1.Lines.Add(j.ToString); //result:{"aaa":"11111","ccc":"333"} j.Free; end; //Function to add array according to path: procedure CreateJSONPathArr(aJson: TJSONObject; const aPath: string; jArr: TJSONArray); var arr: TArray<string>; path: string; i: Integer; begin arr := aPath.Split(['.'], ExcludeEmpty); for i := 0 to Length(arr) - 1 do begin if not aJson.TryGetValue(arr[i], aJson) then begin if i = Length(arr) - 1 then aJson.AddPair(arr[i], jArr) else begin aJson.AddPair(arr[i], TJSONObject.Create); aJson.TryGetValue(arr[i], aJson); end; end; end; end; //Call the test: var j: TJSONObject; a: TJSONArray; begin j := TJSONObject.Create; a := TJSONArray.Create('11', '22'); CreateJSONPathArr(j, 'aaa.bbb.ccc', a); a := TJSONArray.Create('33', '44'); CreateJSONPathArr(j, 'aaa.bbb.ddd', a); j.Free; end;