TQJsonOutputChannel 的主要作用是用来快速写入大型的 JSON 数据到文件中,所以整体是面向写入过程设计的,不要试图用它来控制内容的修改。
假设我们要将数据内容写入到目标数据流 AStream 中:
第一步:我们需要定义一个 IQJsonStreamEncoder 的实例,它是一个结构体,所以直接在栈上定义这个变量即可。
var
AWriter: IQJsonStreamEncoder;
第二步:创建实例并建立与目标数据流的关联:
AWriter := TQJsonOutputChannel.CreateEncoder(teUtf8, AStream);
还有一个最大层数限制,默认为32,可以通过第三个参数修改。
第三步:开始按照正常的规则写入 JSON 数据。
- 调用 BeginArray 开始一个数组定义,它必需在元素输出完成后,对应一个 EndArray 调用来标志此数组输出结束。也可以使用 WriteArray 来定义数组。
- 调用 BeginObject 开始一个对象定义,它必需在子结点输出完成后,对应一个 EndObject 调用来标志此对象输出结束。也可以使用 WriteObject 来定义对象。
- 调用 WriteElement 方法写入数组元素的值
- 调用 WriteChild 方法写入普通类型的值
第四步:已经完事了,补充一点吧,这个写入的JSON是以压缩格式写入的,没有加入缩进支持。可以用TQJsonInputChannel 来顺序读取。
最后,来一段示例代码,Show you my code:
procedure TForm2.SpeedButton1Click(Sender: TObject);
var
AStream: TMemoryStream;
AJson: TQJson;
I: Integer;
AWriter: IQJsonStreamEncoder;
begin
AJson := AcquireJson;
AStream := TMemoryStream.Create;
try
AJson.Add('O').Add('01');
AJson.AddArray('A');
AWriter := TQJsonOutputChannel.CreateEncoder(teUtf8, AStream);
AWriter.BeginArray('');
for I := 0 to 9 do
begin
AWriter.BeginObject('');
AWriter.WriteChild('Ident', 'Json Stream Writer');
AWriter.WriteChild('IntValue', I);
AWriter.WriteChild('FloatValue', Double(1.333 * I));
AWriter.WriteChild('BoolValue', (I mod 2) = 1);
AWriter.WriteChild('NullValue');
AWriter.WriteChild('DateTime', Now);
AJson.ForcePath('O.01').AsString := I.ToString;
AWriter.WriteChild('Json', AJson);
AWriter.EndObject;
end;
AWriter.EndArray;
AStream.Position := 0;
repeat
AJson.LoadFromStream(AStream, teUtf8);
ShowMessage(AJson.Encode(true));
until AStream.Position = AStream.Size;
finally
ReleaseJson(AJson);
FreeAndNil(AStream);
end;
end;
procedure TForm2.SpeedButton2Click(Sender: TObject);
var
AStream: TMemoryStream;
AJson: TQJson;
I: Integer;
AWriter: IQJsonStreamEncoder;
begin
AJson := AcquireJson;
AStream := TMemoryStream.Create;
try
AJson.Add('O').Add('01');
AJson.AddArray('A');
AWriter := TQJsonOutputChannel.CreateEncoder(teUtf8, AStream);
AWriter.WriteArray('',
procedure(AParent: IQJsonArrayEncoder)
var
I: Integer;
begin
for I := 0 to 9 do
begin
AParent.WriteObject(
procedure(AObjParent: IQJsonObjectEncoder)
begin
AObjParent.Write('Ident', 'Json Stream Writer');
AObjParent.Write('IntValue', I);
AObjParent.Write('FloatValue', Double(1.333 * I));
AObjParent.Write('BoolValue', (I mod 2) = 1);
AObjParent.Write('NullValue');
AObjParent.Write('DateTime', Now);
AJson.ForcePath('O.01').AsString := I.ToString;
AObjParent.Write('Json', AJson);
end);
end
end);
AStream.Position := 0;
repeat
AJson.LoadFromStream(AStream, teUtf8);
ShowMessage(AJson.Encode(true));
until AStream.Position = AStream.Size;
finally
ReleaseJson(AJson);
FreeAndNil(AStream);
end;
end;