【问题标题】:Parse an array of strings in JSON解析 JSON 中的字符串数组
【发布时间】:2022-01-04 09:03:02
【问题描述】:

在 Delphi 10 Seattle 中,我试图解析一个 JSON,该 JSON 包含一个属性中的字符串数组。

举个例子,考虑一下:

{
  "name":"Joe",
  "age":45,
  "languages":["c++", "java", "cobol"]
} 

如何解析languages 以获得字符串数组?

【问题讨论】:

标签: arrays json delphi delphi-10-seattle


【解决方案1】:

试试这样的:

function GetLanguagesArray(const AJSON: String): TArray<String>;
var
  LValue: TJSONValue;
  LArray: TJSONArray;
  i: Integer;
begin
  Result := nil;
  LValue := TJSONObject.ParseJSONValue(AJSON);
  if LValue <> nil then
  try
    LArray := (LValue as TJSONObject).GetValue('languages') as TJSONArray;
    SetLength(Result, LArray.Count);
    for i := 0 to Pred(LArray.Count) do
    begin
      Result[i] := LArray[i].Value;
    end;
  finally
    LValue.Free;
  end;
end;

【讨论】:

    【解决方案2】:

    使用 REST.JSON 非常简单,使用 helper 来解析和读取数组项

    type
      TDeveloper = class
      private
        FAge      : Integer;
        FName     : string;
        FLanguages: TArray<string>;
      public
        property Age      : Integer        read FAge       write FAge;
        property Name     : string         read FName      write FName;
        property Languages: TArray<string> read FLanguages write FLanguages;
      end;
    
    // Sample
    var
      FDeveloper: TDeveloper;
      FLanguage : string;
    begin
      try
        FDeveloper := TJson.JsonToObject<TDeveloper>(Memo1.Text);
        Memo2.Clear;
        Memo2.Lines.Add('------------------------------ ');
        Memo2.Lines.Add('Name: ' + FDeveloper.Name);
        Memo2.Lines.Add('Age : ' + FDeveloper.Age.ToString);
    
        for FLanguage in FDeveloper.Languages do
        begin
          Memo2.Lines.Add('------------------------------ ');
          Memo2.Lines.Add(FLanguage);
        end;
      finally
        FreeAndNil(FDeveloper);
      end;
    

    看图: [1]:https://i.stack.imgur.com/69Zao.png

    【讨论】:

      【解决方案3】:
      function TForm1.GetLangArray(const AJSONStr: String): TArray<String>;
      var
        AJSONVal, AJSONElem: TJSONValue;
        AJSONArray: TJSONArray;
        i: Integer;
      begin
        AJSONVal := TJSONObject.ParseJSONValue(AJSONStr);
        AJSONVal := AJSONVal.P['languages'];
      
        if (AJSONVal is TJSONArray) then
          AJSONArray := AJSONVal as TJSONArray
        else
          Exit;
      
        with AJSONArray do
        begin
          SetLength(Result, Count);
          i := 0;
          for AJSONElem in AJSONArray  do
          begin
            Result[i] := AJSONelem.Value;
            Inc(i);
          end;
        end;
      end;
      

      更新

      感谢@RemyLebeau 的评论。我修复了之前代码的内存泄漏:

      function TForm1.GetLangArray(const AJSONStr: String): TArray<String>;
      var
        AJSONVal, AJSONElem: TJSONValue;
        AJSONArray: TJSONArray;
        i: Integer;
      begin
        AJSONVal := TJSONObject.ParseJSONValue(AJSONStr);
        try
          AJSONArray := AJSONVal.P['languages'] as TJSONArray;
      
          with AJSONArray do
          begin
            SetLength(Result, Count);
            i := 0;
            for AJSONElem in AJSONArray  do
            begin
              Result[i] := AJSONElem.Value;
              Inc(i);
            end;
          end;
        finally
          AJSONVal.Free;
        end;
      end;
      

      【讨论】:

      • “AJSONVal.P['languages'];”出现编译器错误
      • @Girish 不,代码很干净。你的编译器错误是什么?
      • 我得到--[dcc32 Error] Unit3.pas(168): E2003 Undeclared identifier: 'P'
      • @Girish 你确定使用了System.JSON 吗?
      • TJSONValue.P[] 属性在西雅图 10.0 中不存在,它是在 10.3 Rio 中添加的。您必须将解析的TJSONValue 类型转换为TJSONObject,然后使用其Values[] 属性或GetValue() 方法访问languages 数组。此外,此代码泄漏了从TJSONObject.ParseJSONValue() 返回的已解析的TJSONValue,您需要在使用完毕后Free()。这意味着使用单独的变量将languages TJSONValue 检索到。
      猜你喜欢
      • 1970-01-01
      • 2013-10-12
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      相关资源
      最近更新 更多