【问题标题】:How to read fairly simple JSON file in Delphi Xe4?如何在 Delphi Xe4 中读取相当简单的 JSON 文件?
【发布时间】:2014-06-28 11:57:56
【问题描述】:

我已经为此苦苦挣扎了一段时间,而做一些简单的事情似乎花费的时间太长了。

我有一个这样的文件:

[
 {
  "FirstName": "Oleg",
  "Surname": "Buckley"
 },
 {
  "FirstName": "Amery",
  "Surname": "Mcmillan"
 },
 {
  "FirstName": "Denton",
  "Surname": "Burnett"
....

我希望能够将它们读入我的程序。到目前为止,我已经完成了这个非常小的功能:

function GetGeneratedNames: TArray<string>;
var fileName: TFileName;
  JSONValue, jv: TJSONValue;
  JSONArray: TJSONArray;
  jo: TJSONObject;
  pair: TJSONPair;
begin
  result := nil;
  filename := ExePath + 'Names.json';
    JSONValue :=  TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0);
    if JSONValue is TJSONArray then begin
     for jv in (JSONValue as TJSONArray) do begin
       if jv is TJSONObject then begin
         jo := jv as TJSONObject;
         for pair in jo do begin
           Append(result, jo.Value);
         end;
       end;
     end;
   end;
end{ GetGeneratedNames};

问题是,它返回一个空白字符串数组。谁能指出我正确的方向?

TIA 标记

【问题讨论】:

  • 尝试改用SuperObject - 整个世界都更轻松。
  • SuperObject 就像O.AsArray[jv].S['FirstName']O.AsArray[jv].S['Surname'] 一样简单
  • 你能说得更具体一点吗?超级对象是什么意思?我在 Embardcadero 源中找不到它。
  • 那是因为它不是 Embarcadero 源的一部分,它是一个第三方库

标签: json delphi delphi-xe4


【解决方案1】:
// XE5- version
uses System.SysUtils, Data.DBXJSON, System.IOUtils;

function GetGeneratedNames: TArray<string>;
var
  fileName: TFileName;
  JSONValue, jv: TJSONValue;
begin
  fileName := TPath.Combine(ExePath, 'Names.json');
  JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
  try
    if JSONValue is TJSONArray then
    begin
      for jv in TJSONArray(JSONValue) do
      begin
        Append(Result, (jv as TJSONObject).Get('FirstName').JSONValue.Value);
        Append(Result, (jv as TJSONObject).Get('Surname').JSONValue.Value);
      end;
    end;
  finally
    JSONValue.Free;
  end;
end { GetGeneratedNames };

// XE6+ version
uses System.SysUtils, System.JSON, System.IOUtils;

function GetGeneratedNames: TArray<string>;
var
  fileName: TFileName;
  JSONValue, jv: TJSONValue;
begin
  fileName := TPath.Combine(ExePath, 'Names.json');
  JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
  try
    if JSONValue is TJSONArray then
    begin
      for jv in TJSONArray(JSONValue) do
      begin
        Append(Result, jv.GetValue<string>('FirstName'));
        Append(Result, jv.GetValue<string>('Surname'));
      end;
    end;
  finally
    JSONValue.Free;
  end;
end { GetGeneratedNames };

【讨论】:

  • 啊,泛型的优雅。 System.JSON 更简单的单元名称表明 JSON 被视为更重要。
  • 幸运的是,我的 Xe4 与 XE5 示例具有相同的形式。成功了!
【解决方案2】:

您没有从数组项中读取正确的值。
试试这样的:

//...
var
  JSONArr: TJSONArray;
  Item: TJSONValue;
  FirstName, Surname, WholeObject: String;
begin
  //...
  JSONArr := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0);
  try
    for Item in JSONArr do
    begin
      // Get the first or last names
      FirstName := (Item as TJSONObject).GetValue('FirstName').Value;
      Surname := (Item as TJSONObject).GetValue('Surname').Value;
      // Get the whole string {"FirstName": "Oleg", "Surname": "Buckley"}
      WholeObject := Item.ToString; 
    end;
  finally
    JSONArr.Free;
  end;
  // do something with them ...
end;

JSON 对象包含值对,但它本身没有值,因此您会得到空字符串。如果你想要整个对象文本,你应该使用“ToString”方法。

如果您碰巧处理大量数据,SuperObjectXSuperObject 确实更易于使用且速度更快。第二个似乎也适用于 iOS/Android,虽然我没有使用过。

【讨论】:

  • 该代码看起来不错且可读。 JSONArr 是从哪里来的呢?它没有被分配。
  • JSONValue 实际上应该是JSONArr
【解决方案3】:

感谢 tz 和 VGeorgiev。这是代码的最终形式,与您的代码密切相关:

function GetGeneratedNames: TArray<string>;
var data: TBytes;
    JSONValue, jv: TJSONValue;
    joName: TJSONObject;
    firstName, surname: string;
begin
  result := nil;
  data := TEncoding.ASCII.GetBytes(TFile.ReadAllText(ExePath + 'Names.json'));
  JSONValue := TJSONObject.ParseJSONValue(data, 0);
  for jv in JSONValue as TJSONArray do begin  // Returns TJSONValue
    joName := jv as TJSONObject;
    firstName := joName.Get('FirstName').JSONValue.Value;
    surname := joName.Get('Surname').JSONValue.Value;
    Append(Result, surname + ', ' + firstName);
  end{for};
end{ GetGeneratedNames};

【讨论】:

    猜你喜欢
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    相关资源
    最近更新 更多