DatasetAdapter
,以对象数组的形式将数据集导出和导入到标准 JSON,而没有 FDDataset.SaveToStream(Stream, sfJSON)
包含的所有怪异之处,从而产生更短、更干净的文件。
这是我将数据集导出和后期导入到简单 JSON 的快速演示:
// We clear prior JSON export files
if TFile.Exists('export.json') then
TFile.Delete('export.json');
// We create a source Dataset
var LSource := TFDMemTable.Create(Self);
LSource.CachedUpdates := True;
LSource.FieldDefs.Add('id', ftInteger);
LSource.FieldDefs.Add('description', ftWideString, 100);
// We populate the source Dataset
LSource.CreateDataSet;
LSource.Append;
LSource.FieldValues['id'] := 1;
LSource.FieldValues['description'] := 'apples';
LSource.Post;
LSource.Append;
LSource.FieldValues['id'] := 2;
LSource.FieldValues['description'] := 'oranges';
LSource.Post;
// We create the objects to export that Dataset to JSON
var LRequest := TRESTRequest.Create(Self);
var LRequestAdapter := TRESTRequestDataSetAdapter.Create(Self);
LRequestAdapter.Request := LRequest;
LRequestAdapter.AutoUpdate := false;
LRequestAdapter.Dataset := LSource;
// We export the source Dataset to JSON
LRequestAdapter.UpdateParameter;
TFile.WriteAllText('export.json', LRequest.GetFullRequestBody);
// We create a target Dataset
var LTarget := TFDMemTable.Create(Self);
LTarget.CachedUpdates := True;
LTarget.FetchOptions.Items := [];
LTarget.FieldDefs.Add('id', ftInteger);
LTarget.FieldDefs.Add('description', ftWideString, 100);
// We create the objects to import our JSON data to the target Dataset
var LResponseAdapter := TCustomJSONDatasetAdapter.Create(Self);
LResponseAdapter.Dataset := LTarget;
// We import the JSON data to the target Dataset
LResponseAdapter.UpdateDataSet(TJSONValue.ParseJSONValue(TFile.ReadAllText('export.json')));
// We check that the target contains the same data we populated into the source
ShowMessage('RowCount: ' + LTarget.RecordCount.ToString + ', First Row: ' + LTarget.FieldByName('Description').AsString);
它工作得很好,但我想知道 - 我可以避免在导出过程中使用中间
TRESTRequest
吗?大多数时候,我希望将生成的 JSON 放入 RAD 服务器的 TEndpointResponse
,而不是放入 TRESTRequest
。
DatasetAdapter
单元提供了TCustomJSONDatasetAdapter
类,可以将直接JSON导入到数据集中,而无需从TRESTResponse
读取它们。但我在该单元中找不到允许将数据集直接导出到 JSON 的类似类(因此我可以将该 JSON 放入 EndpointResponse
中,或进一步操作该 JSON,例如将其中几个保存到单个文件中以减少到后端的往返等)。我不想将该数据集导出到我真正不会使用的 TRESTRequest
体内,从而减慢进程并增加不必要的内存使用。
按照 Uwe Raabe 的建议,我使用底层 TDataSetToJSONBridge 类(Data.DBJson 单元)而不是 TRESTRequestDataSetAdapter,现在我可以直接获取导出 JSON。
// We clear prior JSON export files
if TFile.Exists('export.json') then
TFile.Delete('export.json');
// We create a source Dataset
var LSource := TFDMemTable.Create(Self);
LSource.CachedUpdates := True;
LSource.FieldDefs.Add('id', ftInteger);
LSource.FieldDefs.Add('description', ftWideString, 100);
// We populate the source Dataset
LSource.CreateDataSet;
LSource.Append;
LSource.FieldValues['id'] := 1;
LSource.FieldValues['description'] := 'apples';
LSource.Post;
LSource.Append;
LSource.FieldValues['id'] := 2;
LSource.FieldValues['description'] := 'oranges';
LSource.Post;
// We export the source Dataset to JSON
var ToJSONBridge := TDatasetToJSONBridge.Create;
ToJSONBridge.Dataset := LSource;
TFile.WriteAllText('export.json', ToJSONBridge.Produce.ToString);
// We create a target Dataset
var LTarget := TFDMemTable.Create(Self);
LTarget.CachedUpdates := True;
LTarget.FetchOptions.Items := [];
LTarget.FieldDefs.Add('id', ftInteger);
LTarget.FieldDefs.Add('description', ftWideString, 100);
// We import the JSON data to the target Dataset
var LResponseAdapter := TCustomJSONDatasetAdapter.Create(Self);
LResponseAdapter.Dataset := LTarget;
LResponseAdapter.UpdateDataSet(TJSONValue.ParseJSONValue(TFile.ReadAllText('export.json')));
// We check that the target contains the same data we populated into the source
ShowMessage('RowCount: ' + LTarget.RecordCount.ToString + ', First Row: ' + LTarget.FieldByName('Description').AsString);
简单多了,而且看起来效果很好。谢谢乌韦。