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

vpfxa7rd  于 2023-05-28  发布在  其他
关注(0)|答案(3)|浏览(166)

我使用TRestClient>TRestRequest>TRestResponse>TRESTResponseDataSetAdapter从Rest API中检索JSON数据。这很好用,我在内存中创建了一个TClientDataset

// 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;

然后,我可以将数据读入字段:

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;

然后我可以将DataField分配给GUI上的一个组件(部分屏幕截图):

你可以从这里看到我的问题是什么。Department字段是一个嵌套元素,我不知道如何访问{"name":"Finance","id":29111}来显示Finance。
我已经尝试了各种解决类似问题的方法,但找不到一个有效的方法。

mbyulnm0

mbyulnm01#

您可以使用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');
9nvpjoqh

9nvpjoqh2#

您可以创建嵌套的ClientDataSet来处理DataBinding。下面是我的例子:

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

  // Create the DataSet
  gStaffTable.CreateDataSet;
end;

在这段代码中,我们首先定义数据集的主要字段。然后,我们为“Department”结构定义一个嵌套字段,它包含一个“Name”和一个“id”。在定义了字段的结构之后,我们调用CreateDataSet来完成数据集结构。
现在,您有了一个与JSON结构相对应的嵌套ClientDataSet,您可以使用它来绑定数据。请注意,您需要手动或通过另一个DataBinding机制处理从JSON到数据集的数据分配。

iecba09b

iecba09b3#

向数据集“DepartmentName”添加另一个字段,然后在他身上设置TField.OnGetText事件。
过程GetDepartmentNameValue应该从JSON中提取数据如果你想将值设置为finance,请使用过程来完成

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;

相关问题