[教程]使用 TQJsonOutputChannel 写入 JSON 数据到流中

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;
分享到: