使用Delphi中的TClientDataset检索嵌套的JSON字段的正确方法是什么?

huangapple go评论59阅读模式
英文:

What is the proper way to retrieve a nested JSON field using TClientDataset in Delphi?

问题

I am using TRestClient>TRestRequest>TRestResponse>TRESTResponseDataSetAdapter to retrieve JSON data from a Rest API. This works well and I create a TClientDataset in memory:

  // 创建一个新的内存数据集
  gStaffTable := TClientDataset.Create(nil);

  with gStaffTable do
  begin
    // 向其中添加一些字段
    FieldDefs.Add('FirstName', ftString, 255, False);         //0
    FieldDefs.Add('MiddleName', ftString, 255, False);        //1
    FieldDefs.Add('LastName', ftString, 255, False);          //2
    // ...在这里添加其他字段 3..26
    // Department 是一个嵌套字段
    FieldDefs.Add('Department', ftString, 255, False);        //27

    // 创建数据集
    CreateDataSet;
    // 添加 AfterScroll 过程
    AfterScroll := gStaffTableAfterScroll;
    OnCalcFields := gStaffTableOnCalcFields;

    IndexFieldNames := 'FullName';
    Open;
    FieldByName('Firstname').DisplayLabel := 'First Name';
    FieldByName('MiddleName').DisplayLabel := 'Middle Name';
    //.. 添加其余的显示标签
   end;

I can then read my data into the fields:

  ClientDataset.First;
  while not ClientDataSet.EOF do
  begin
    with gStaffTable do
    begin
      try
        application.ProcessMessages;
        append;
          FieldbyName('Firstname').AsString := ClientDataSetfirst_name.AsString;
          FieldbyName('LastName').AsString := ClientDataSetlast_name.AsString;
          FieldbyName('Fullname').AsString := ClientDataSetfirst_name.AsString + ' ' + 
          //.. 对其余字段执行相同操作
          
          // Department 是一个嵌套字段 - 需要修改以读取部门名称
          // {"name":"Finance","id":29111}
          FieldbyName('Department').AsString :=  ClientDataSet.FieldByName('Department').AsString;

        post;
      except

      end;
    end;
    application.ProcessMessages;
    ClientDataSet.Next;
  end;

I can then just assign the DataField to a component on the GUI (partial screen snip):

使用Delphi中的TClientDataset检索嵌套的JSON字段的正确方法是什么?

你可以从中看出我的问题所在。Department 字段是一个嵌套元素,我无法弄清楚如何访问{"name":"Finance","id":29111}以显示 Finance。

我已尝试了解决类似问题的各种方法,但没有找到有效的解决方案。

英文:

I am using TRestClient>TRestRequest>TRestResponse>TRESTResponseDataSetAdapter to retrieve JSON data from a Rest API. This works well and I create a TClientDataset in memory:

  // Create a new in memory dataset
  gStaffTable := TClientDataset.Create(nil);

  with gStaffTable do
  begin
    // Add some fields to it
    FieldDefs.Add('FirstName', ftString, 255, False);         //0
    FieldDefs.Add('MiddleName', ftString, 255, False);        //1
    FieldDefs.Add('LastName', ftString, 255, False);          //2
    // ...add the other fields 3..26 here
    // Department is a nested field
    FieldDefs.Add('Department', ftString, 255, False);        //27

    // Create it
    CreateDataSet;
    // Add an AfterScroll procedure
    AfterScroll := gStaffTableAfterScroll;
    OnCalcFields := gStaffTableOnCalcFields;

    IndexFieldNames := 'FullName';
    Open;
    FieldByName('Firstname').DisplayLabel := 'First Name';
    FieldByName('MiddleName').DisplayLabel := 'Middle Name';
    //.. add the rest of the displaylabels here
 
   end;

I can then read my data into the fields:

  ClientDataset.First;
  while not ClientDataSet.EOF do
  begin
    with gStaffTable do
    begin
      try
        application.ProcessMessages;
        append;
          FieldbyName('Firstname').AsString := ClientDataSetfirst_name.AsString;
          FieldbyName('LastName').AsString := ClientDataSetlast_name.AsString;
          FieldbyName('Fullname').AsString := ClientDataSetfirst_name.AsString + ' ' + 
          //.. do the same for the rest of the fields
          
          // Department is a nested field - need to modify this to read the department name
          // {"name":"Finance","id":29111}
          FieldbyName('Department').AsString :=  ClientDataSet.FieldByName('Department').AsString;

        post;
      except

      end;
    end;
    application.ProcessMessages;
    ClientDataSet.Next;
  end;

I can then just assign the DataField to a component on the GUI (partial screen snip):

使用Delphi中的TClientDataset检索嵌套的JSON字段的正确方法是什么?

You can see from this what my problem is. The Department field is a nested element and I cannot figure out how to access {"name":"Finance","id":29111} to display Finance.

I have tried various resolutions to similar problems but cannot find one that works.

答案1

得分: 0

你可以使用 TJSONObject.ParseJSONValue 类函数来解析 JSON 字符串。

例如,你可以定义一个函数来提取该值:

uses
  System.JSON;

function ExtractPairStringValue(const AJSONString: string; const APairName: string): string;
var
  Obj: TJSONValue;
begin
  Obj := TJSONObject.ParseJSONValue(AJSONString);
  try
    Result := Obj.GetValue<string>(APairName);
  finally
    Obj.Free;
  end;
end;

然后,你可以像这样提取该值:

FieldByName('Department').AsString := ExtractPairStringValue(ClientDataSet.FieldByName('Department').AsString, 'name');
英文:

You can use the TJSONObject.ParseJSONValue class function for parsing the JSON string.

For example, you can define a function to extract the value:

uses
  System.JSON;

function ExtractPairStringValue(const AJSONString : string; const APairName : string) : string;
var
  Obj : TJSONValue;
begin
  Obj := TJSONObject.ParseJSONValue(AJSONString);
  try
    Result := Obj.GetValue&lt;string&gt;(APairName);
  finally
    Obj.Free;
  end;
end;

Then you'll be able to extract the value like this:

FieldByName(&#39;Department&#39;).AsString := ExtractPairStringValue(ClientDataSet.FieldByName(&#39;Department&#39;).AsString, &#39;name&#39;);

答案2

得分: 0

你可以创建一个嵌套的 ClientDataSet 来处理数据绑定。以下是我的示例:

var
  gStaffTable: TClientDataSet;
begin
  gStaffTable := ClientDataSet1;

  with gStaffTable do
  begin
    // 添加字段
    FieldDefs.Add('FirstName', ftString, 255, False);        // 0
    FieldDefs.Add('MiddleName', ftString, 255, False);       // 1
    FieldDefs.Add('LastName', ftString, 255, False);         // 2

    // 为 'Department' 结构定义一个嵌套字段
    with FieldDefs.AddFieldDef do
    begin
      Name := 'Department';
      DataType := ftDataSet;
      ChildDefs.Add('Name', ftString, 255, False);
      ChildDefs.Add('id', ftInteger);
    end;
  end;

  // 创建数据集
  gStaffTable.CreateDataSet;
end;

在这段代码中,我们首先定义了数据集的主要字段。然后,我们为 'Department' 结构定义了一个嵌套字段,其中包含 'Name' 和 'id'。在定义字段结构后,我们调用 CreateDataSet 来最终确定数据集的结构。

现在,你有一个与你的 JSON 结构对应的嵌套 ClientDataSet,你可以使用它来绑定你的数据。请注意,你需要手动处理从 JSON 到数据集的数据赋值,或通过其他数据绑定机制来完成。

英文:

You can create a nested ClientDataSet to handle DataBinding. Here's my example:

var
  gStaffTable: TClientDataSet;
begin
  gStaffTable := ClientDataSet1;
  
  with gStaffTable do
  begin
    // Add fields
    FieldDefs.Add(&#39;FirstName&#39;, ftString, 255, False);         //0
    FieldDefs.Add(&#39;MiddleName&#39;, ftString, 255, False);        //1
    FieldDefs.Add(&#39;LastName&#39;, ftString, 255, False);          //2
  
    // Define a nested field for the &#39;Department&#39; structure
    with FieldDefs.AddFieldDef do
    begin
      Name := &#39;Department&#39;;
      DataType := ftDataSet;
      ChildDefs.Add(&#39;Name&#39;, ftString, 255, False);
      ChildDefs.Add(&#39;id&#39;, ftInteger);
    end;
  end;

  // Create the DataSet
  gStaffTable.CreateDataSet;
end;

In this code, we first define the main fields of the dataset. Then, we define a nested field for the 'Department' structure, which contains a 'Name' and an 'id'. After defining the structure of our fields, we call CreateDataSet to finalize the dataset structure.

Now, you have a nested ClientDataSet that corresponds to your JSON structure, and you can use this to bind your data. Please note that you will need to handle the data assignment from the JSON to the dataset manually or via another DataBinding mechanism.

答案3

得分: -1

Add another field to dataset "DepartmentName" then set a TField.OnGetText event on it.

procedure GetDepartmentNameValue should extract data from JSON
If you want to set value to finance, create a procedure to do it

procedure TForm1.FieldOnGetText(Sender: TField; var Text: string;
  DisplayText: Boolean);
begin
    Text := GetDepartmentNameValue(Sender);
end;

procedure TForm1.FieldOnSetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  SetDepartmentNameValue(sender, Text);
end;
英文:

Add another field to dataset "DepartmentName" then set an TField.OnGetText event on him.

procedure GetDepartmentNameValue should extract data from JSON
If you want to set value to finance make procedure to do it

procedure TForm1.FieldOnGetText(Sender: TField; var Text: string;
  DisplayText: Boolean);
begin
    Text := GetDepartmentNameValue(Sender);
end;

procedure TForm1.FieldOnSetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  SetDepartmentNameValue(sender, Text);
end;

huangapple
  • 本文由 发表于 2023年5月25日 18:41:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331408.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定