Home > Software engineering >  How to parse JSON in Delphi?
How to parse JSON in Delphi?

Time:06-11

I have a JSON like this:

{
"Content": [{
    "Identifier": "AABBCC",
    "Description": "test terfdfg",
    "GenericProductIdentifier": "AABBCC",
    "ProductFamilyDescription": "sampling",
    "LifeCycleStatus": "ACTIVE",
    "Price": {
        "Value": 1.00,
        "Quantity": 1000
    },
    "LeadTimeWeeks": "16",
    "FullBoxQty": 200,
}],
"TotalElements": 1,
"TotalPages": 1,
"NumberOfElements": 1,
"First": true,
"Size": 1,
"Number": 0
}

In Delphi 10.4, I'm trying to parse it, but I can't access the values ​​contained in 'Price'.

I wrote code like this:

var
  vContent: TJSONArray;
  vJson: TJSONObject;
  vContentRow: TJSONObject;
  i,j : Integer;
begin
  Memo2.Lines.Clear;

  if Memo1.Text = '' then
    exit;

  vJson := TJSONObject(TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(Memo1.Text),0));
  try
    vContent := TJSONArray(vJson.Get('Content').JsonValue);

    for i := 0 to Pred(vContent.Count) do
    begin
      vContentRow := TJSONObject(vContent.Items[i]);
      for j := 0 to Pred(vContentRow.Count) do
      begin
        Memo2.Lines.Add('  '  vContentRow.Get(j).JsonString.Value ' : '  vContentRow.Get(j).JsonValue.Value);
      end;
    end;

    Memo2.Lines.Add(vContent.Value);
  finally

  end;
end;

What is the correct way to read the values ​​contained in 'Price'?

CodePudding user response:

Here is a sample code to parse your JSON:

uses
  System.IOUtils, System.JSON, System.Generics.Collections;

procedure TForm1.Button1Click(Sender: TObject);

  procedure GetPrices(const S: string);
  var
    V: TJsonValue;
    O, E, P: TJsonObject;
    A: TJsonArray;
  begin
    V := TJSONObject.ParseJSONValue(S);
    if not Assigned(V) then
      raise Exception.Create('Invalid JSON');
    try
      O := V as TJSONObject;
      A := O.GetValue<TJsonArray>('Content');
      for var I := 0 to A.Count - 1 do
      begin
        E := A.Items[I] as TJsonObject; // Element
        P := E.GetValue<TJsonObject>('Price');
        ShowMessage('Value: '   P.GetValue<string>('Value')   '  '   'Quantity: '    P.GetValue<string>('Quantity'));
      end;
    finally
      V.Free;
    end;
  end;

var
  S: string;
begin
  S := TFile.ReadAllText('d:\json.txt'); // Retrieve it using some webservice
  GetPrices(S);
end;

Note, your JSON is invalid, the corect definition is:

{
    "Content": [{
        "Identifier": "AABBCC",
        "Description": "test terfdfg",
        "GenericProductIdentifier": "AABBCC",
        "ProductFamilyDescription": "sampling",
        "LifeCycleStatus": "ACTIVE",
        "Price": {
            "Value": 1.00,
            "Quantity": 1000
        },
        "LeadTimeWeeks": "16",
        "FullBoxQty": 200
    }],
    "TotalElements": 1,
    "TotalPages": 1,
    "NumberOfElements": 1,
    "First": true,
    "Size": 1,
    "Number": 0
}

CodePudding user response:

You can use the JSON library of Delphi. The JSON library has the JsonToObject class function that can convert directly the string to an Object (Object structure)

See this: https://docwiki.embarcadero.com/Libraries/Sydney/en/REST.Json.TJson.JsonToObject

You can create the classes structure manually o using the web: https://jsontodelphi.com/

The classes structure for your JSON created is this:

type
  TPrice = class;

  TPrice = class
  private
    FQuantity: Integer;
    FValue: Double;
  published
    property Quantity: Integer read FQuantity write FQuantity;
    property Value: Double read FValue write FValue;
  end;
  
  TContent = class
  private
    FDescription: string;
    FFullBoxQty: Integer;
    FGenericProductIdentifier: string;
    FIdentifier: string;
    FLeadTimeWeeks: string;
    FLifeCycleStatus: string;
    FPrice: TPrice;
    FProductFamilyDescription: string;
  published
    property Description: string read FDescription write FDescription;
    property FullBoxQty: Integer read FFullBoxQty write FFullBoxQty;
    property GenericProductIdentifier: string read FGenericProductIdentifier write FGenericProductIdentifier;
    property Identifier: string read FIdentifier write FIdentifier;
    property LeadTimeWeeks: string read FLeadTimeWeeks write FLeadTimeWeeks;
    property LifeCycleStatus: string read FLifeCycleStatus write FLifeCycleStatus;
    property Price: TPrice read FPrice;
    property ProductFamilyDescription: string read FProductFamilyDescription write FProductFamilyDescription;
  public
    constructor Create;
    destructor Destroy; override;
  end;
  
  TRoot = class(TJsonDTO)
  private
    [JSONName('Content'), JSONMarshalled(False)]
    FContentArray: TArray<TContent>;
    [GenericListReflect]
    FContent: TObjectList<TContent>;
    FFirst: Boolean;
    FNumber: Integer;
    FNumberOfElements: Integer;
    FSize: Integer;
    FTotalElements: Integer;
    FTotalPages: Integer;
    function GetContent: TObjectList<TContent>;
  protected
    function GetAsJson: string; override;
  published
    property Content: TObjectList<TContent> read GetContent;
    property First: Boolean read FFirst write FFirst;
    property Number: Integer read FNumber write FNumber;
    property NumberOfElements: Integer read FNumberOfElements write FNumberOfElements;
    property Size: Integer read FSize write FSize;
    property TotalElements: Integer read FTotalElements write FTotalElements;
    property TotalPages: Integer read FTotalPages write FTotalPages;
  public
    destructor Destroy; override;
  end;

Now, the code for parse elements is more simple. You only need a code like this to access different properties of your structure:

var
  Root: TRoot;
begin
  root := TJSON.JsonToObject<TRoot>(Memo1.Lines.Text);
  lblid.Caption := 'TotalElements: '   Root.TotalElements.ToString;
  lblvalue.Caption := 'TotalPages: '   Root.TotalPages.ToString;
  lblcount.Caption := 'Identifier: '   Root.Content[0].Identifier;
  lblfirstonclick.Caption := 'Description: '   Root.Content[0].Description;
  lbllastonclick.Caption := 'Price/Quantity:'   Root.Content[0].Price.Quantity.ToString;
  //...
  • Related