• 关于内存数据与 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(或 XML);之前一直使用 SuperObject,以后会使用 System.JSON 更多些。

    System.JSON?还是 SuperObject?

    System.JSON 是官方的;这省去很多麻烦,这也是我考虑它的主要原因。

    System.JSON “读写文件” 与 “格式化” 等功能,都有的功能也不如 SuperObject 方便。

    System.JSON 主要考虑的是:从服务器生成 json,然后传输到客户端(特别是给 JavaScript 使用),不像 SuperObject 大而全。

    如果不是太复杂的 json 应用,优先考虑 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); //TJSONArray 不像传统的数组,它可以接受几种不同类型的值;这应该算是对 Delphi 数组功能的扩充吧。
      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
      j.Free;
    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:	emp');
    
      //写入文件
      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');
      j.AddPair('ccc', '333');
    
      //修改
      j.Get('aaa').JsonValue := TJSONString.Create('11111'); //TJSONPair 的 JsonString、JsonValue 分别是 键、值
    //  j.Pairs[0].JsonValue := TJSONString.Create('11111');
    
      //删除
      j.RemovePair('bbb');
    
      Memo1.Lines.Add(j.ToString); //结果:{"aaa":"11111","ccc":"333"}
    
      j.Free;
    end;
    
    //根据路径添加数组的函数:
    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;
    
    //调用测试:
    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;
    
    

  • 相关阅读:
    二叉排序树(B-Tree)-c实现
    队列(Queue)-c实现
    栈(stack)--c实现(使用双链表)
    链表(list)--c实现
    c 和 指针读书笔记(1)
    c traps and pitfalls reading notes(2)
    js 控制
    正则表达式
    Android 笔记
    Android 布局方式学习
  • 原文地址:https://www.cnblogs.com/del/p/4225871.html
走看看 - 开发者的网上家园