QJson中添加结点主要有以下3种方式:
1、用Add函数
如我们要添加一个字符串类型的子结点:
var
   AJson:TQJson;
begin
AJson:=TQJson.Create;
AJson.Add('Name').AsString:='Jony smith';
...
FreeAndNil(AJson);
end;Add函数有很多重载形式,我们先大概了解一下:
function Add(ANode: TQJson): Integer; overload; function Add: TQJson; overload; function Add(AName, AValue: QStringW;ADataType: TQJsonDataType = jdtUnknown): Integer; overload; function Add(const AName: QStringW; AItems: array of const): TQJson; overload; function Add(AName: QStringW; ADataType: TQJsonDataType): TQJson; overload; function Add(AName: QStringW; AValue: Extended): TQJson; overload; function Add(AName: QStringW; AValue: Int64): TQJson; overload; function Add(AName: QStringW; AValue: Boolean): TQJson; overload; function Add(AName: QStringW; AChild: TQJson): Integer; overload; function AddArray(AName: QStringW): TQJson; overload; function AddDateTime(AName: QStringW; AValue: TDateTime): TQJson; overload; function AddVariant(AName: QStringW; AValue: Variant): TQJson; overload; function Add(AName: QStringW): TQJson; overload; virtual;
(1)是直接添加一个Json结点到当前结点下,传递的是一个Json结点对象,注意添加后这个结点不应该再手工释放。
(2)是添加一个匿名的Json结点,一般用于添加数组的子元素,因为数组元素是没有名称的。
(3)添加一个指定名称和字符串值的结点,其中,AValue对象的值类型由ADataType参数指定,如果未指定,则QJson会自动检测并转换为匹配的类型。
(4)添加一个数组结点,结点的值为一个开放数组。如下面的代码就可以直接添加一个名为 Array 的数组结点,其中有 4 个元素,分别是整数 1 ,字符串 goods ,布尔值 true 和浮点数 3.4:
AJson.Add('Array', [1, 'goods', true, 3.4]);(5)添加一个指定名称和类型的结点。
(6)添加一个指定名称和值的浮点数结点。
(7)添加一个指定名称和值的64位整数结点。
(8)添加一个指定名称和值的布尔结点。
(9)将一个已有的结点以指定的名称附加到当前结点上。
(10)添加一个数组类型的结点,等价于Add(AName,jdtArray)。
(11)添加一个指定名称和值的日期时间类型的结点。
(12)添加一个可变类型的子结点,类型会根据Variant值的内容自动确定。
(13)添加一个指定名称的空白子结点。这是我们常用的一种方法,然后通过AsXXX来为结点赋值,如:
AJson.Add('StringNode').AsString:='String Value';
AJson.Add('IntNode').AsInteger:=100;
AJson.Add('FloatNode').AsFloat:=1.34;2、使用ForcePath函数来确保指定的路径存在。
ForcePath会检查指定的路径是否存在,如果不存在,会创建指定的路径。路径的分隔符可以是 “.” 、 “\” 、 “/” 三者之一,两个连续的分隔符会被忽略。QJson的路径按以下规则处理:
(1)、路径始终是以当前Json结点为根结点;
(2)、对象或者数组都可以使用数组方式来访问,下标从0开始。但如果省略数组的索引,则默认是第一个元素,如:
AJson.ForcePath('a.b.c[].d').AsString:='OK';其结果如下:
{
  "a":{
    "b":{
      "c":[
        {
          "d":"OK"
        }
      ]
    }
  }
}可以看到,c[].d实际被当成了c[0].d。
3、直接使用FromRtti/FromRecord方式添加。
此组函数是基于RTTI来自动将结构体或对象的数据生成对应的Json结构,注意一点,对象只会处理它的published成员,而结构是处理所有的成员。无论对象和结构体,不要出现循环定义的情况,否则会出现内存或堆栈溢出。
var
  ARec: TRttiTestSubRecord;
  AJson: TQJson;
begin
ARec.Int64Val := 1;
ARec.UInt64Val := 2;
ARec.UStr := 'Test String';
ARec.AStr := 'AnsiString';
ARec.SStr := 'ShortString';
ARec.IntVal := 3;
ARec.MethodVal := Button2Click;
ARec.SetVal := [{$IFDEF UNICODE}TBorderIcon.{$ENDIF}biSystemMenu];
ARec.WordVal := 4;
ARec.ByteVal := 5;
ARec.ObjVal := Button2;
ARec.DtValue := Now;
ARec.tmValue := Time;
ARec.dValue := Now;
ARec.CardinalVal := 6;
ARec.ShortVal := 7;
ARec.CurrVal := 8.9;
ARec.EnumVal := {$IFDEF UNICODE}TAlign.{$ENDIF}alTop;
ARec.CharVal := 'A';
ARec.VarVal := VarArrayOf(['VariantArray', 1, 2.5, true, false]);
SetLength(ARec.ArrayVal, 3);
ARec.ArrayVal[0] := 100;
ARec.ArrayVal[1] := 101;
ARec.ArrayVal[2] := 102;
SetLength(ARec.IntArray, 2);
ARec.IntArray[0] := 300;
ARec.IntArray[1] := 200;
AJson := TQJson.Create;
try
  AJson.Add('Record').FromRecord<TRttiTestSubRecord>(ARec);
finally
  FreeAndNil(AJson);
end;
end;在使用此种方式添加结点时,相关注意事项请参考文章:QJson/QMsgPack RTTI 注意事项。
