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 注意事项。