Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   JSON iterieren, aber wie? (https://www.delphipraxis.net/210872-json-iterieren-aber-wie.html)

stifflersmom 24. Jun 2022 08:13

JSON iterieren, aber wie?
 
Moin,

ich stehe hier gerade ein wenig auf dem Schlauch und bräuchte mal eine Hilfestellung.

Gegeben ist folgendes JSON:
Code:
{
    "data": [
        {
            "article": {
                "id": 12472,
                "sku": "AAXXX165",
                "name": "Außenspiegel links elektrisch verstellbar Temperatursensor 5 W langer Spiegelarm",
                "manufacturer": "Originalgerätehersteller (Original Equipment Manufacturer)",
                "price": 12345.5,
                "quality": "Ident",
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2016-02-13 16:30:43",
                "updated_at": null,
                "oe_number": null,
                "stock": 1,
                "weight": 3.48,
                "unit": {
                    "amount": 64.925,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        0,
                        "mm"
                    ],
                    "width": [
                        0,
                        "mm"
                    ],
                    "height": [
                        0,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        },
        {
            "article": {
                "id": 12475,
                "sku": "AAXXX168",
                "name": "Außenspiegel links elektrisch verstellbar 16 W langer Spiegelarm",
                "manufacturer": "Originalgerätehersteller (Original Equipment Manufacturer)",
                "price": 12345.8,
                "quality": "Ident",
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2016-02-13 16:30:43",
                "updated_at": null,
                "oe_number": null,
                "stock": 91,
                "weight": 3.48,
                "unit": {
                    "amount": 64.09,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        500,
                        "mm"
                    ],
                    "width": [
                        400,
                        "mm"
                    ],
                    "height": [
                        230,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        },
        {
            "article": {
                "id": 12476,
                "sku": "AAXXX169",
                "name": "Außenspiegel links elektrisch verstellbar Temperatursensor 16W langer Spiegelarm",
                "manufacturer": "Originalgerätehersteller (Original Equipment Manufacturer)",
                "price": 12345.5,
                "quality": "Ident",
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2016-02-13 16:30:43",
                "updated_at": null,
                "oe_number": null,
                "stock": 322,
                "weight": 3.48,
                "unit": {
                    "amount": 64.925,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        500,
                        "mm"
                    ],
                    "width": [
                        400,
                        "mm"
                    ],
                    "height": [
                        230,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        },
        {
            "article": {
                "id": 22684,
                "sku": "AAXXX169OE",
                "name": "Außenspiegel links elektrisch verstellbar Temperatursensor 16W langer Spiegelarm Original",
                "manufacturer": "Original Ersatzteil (genuine part)",
                "price": 123456.75,
                "quality": null,
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2016-02-13 16:30:47",
                "updated_at": null,
                "oe_number": null,
                "stock": 1,
                "weight": 3.5,
                "unit": {
                    "amount": 190.894,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        530,
                        "mm"
                    ],
                    "width": [
                        500,
                        "mm"
                    ],
                    "height": [
                        230,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        },
        {
            "article": {
                "id": 30970,
                "sku": "AAXXX169MM",
                "name": "Außenspiegel links elektrisch verstellbar Temperatursensor 16W langer Spiegelarm Magneti Marelli",
                "manufacturer": "Marelli Aftermarket Germany GmbH",
                "price": 123454.26,
                "quality": null,
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2016-08-18 15:47:22",
                "updated_at": null,
                "oe_number": null,
                "stock": 54,
                "weight": 3.45,
                "unit": {
                    "amount": 80.004,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        240,
                        "mm"
                    ],
                    "width": [
                        460,
                        "mm"
                    ],
                    "height": [
                        520,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        },
        {
            "article": {
                "id": 41961,
                "sku": "7870019",
                "name": "Satz Spiegel rechts & links elektrisch mit Temperatursensor 16 W",
                "manufacturer": "Bosch/Siemens",
                "price": 123456.4,
                "quality": "Ident",
                "deposit": null,
                "deposit_article_sku": null,
                "created_at": "2017-08-15 12:19:24",
                "updated_at": null,
                "oe_number": null,
                "stock": 1,
                "weight": 6.9,
                "unit": {
                    "amount": 127.872,
                    "unit": "Stk."
                },
                "dimensions": {
                    "length": [
                        0,
                        "mm"
                    ],
                    "width": [
                        0,
                        "mm"
                    ],
                    "height": [
                        0,
                        "mm"
                    ]
                },
                "important_information": {
                    "hazard_warnings": null
                }
            }
        }
    ],
    "meta": {
        "pagination": {
            "total": 6,
            "count": 6,
            "per_page": 100,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}
Wie kann ich jetzt, in diesem Falkl die sechs Artikel (article) druchiterieren um an die einzelnen Werte zu kommen, über einen kurzen Tipp wäre ich dankbar.

Gruß

DeddyH 24. Jun 2022 08:28

AW: JSON iterieren, aber wie?
 
Ohne Fehlerbehandlung schnell heruntergetippt:
Delphi-Quellcode:
procedure TForm3.Button1Click(Sender: TObject);
var
  SL: TStringList;
  obj: TJSONObject;
  arr: TJSONArray;
  i: integer;
  subobj: TJSONObject;
begin
  obj := nil;
  SL := TStringList.Create;
  try
    SL.LoadFromFile('C:\temp\TestJSON.txt'); // Das JSON aus Deinem Post
    obj := TJsonObject.ParseJSONValue(SL.Text) as TJSONObject;
    arr := obj.Values['data'] as TJSONArray;
    for i := 0 to arr.Count - 1 do
      begin
        subobj := (arr.Items[i] as TJSONObject).Values['article'] as TJSONObject;
        ShowMessage(subobj.Values['sku'].Value);
      end;
  finally
    SL.Free;
    obj.Free;
  end;
end;

Maliko 24. Jun 2022 08:35

AW: JSON iterieren, aber wie?
 
Es gibt folgende Funktion:

Delphi-Quellcode:
TJson.JsonToObject<TClass>(sJsonString)
Damit kannst du einen JSON-String in ein Objekt umwandeln. Allerdings musst du dafür eine Objektstruktur in Form von Datenklassen haben, welche du als TClass übergeben kannst. Und das System funktioniert nicht mit TList, sondern nur mit Arrays. Ansonsten hat Uwe Raabe (der ist auch hier im Forum vertreten) vor längerer Zeit mal einen Artikel zu dem Thema auf seine Webseite gestellt. https://www.uweraabe.de/Blog/2020/03...ts-with-tjson/

Vielleicht kannst du damit mehr anfangen.

Der schöne Günther 24. Jun 2022 08:40

AW: JSON iterieren, aber wie?
 
Das gegebene ist ein TJsonObject.
Es enthält das TJsonArray mit dem Namen "data". Das enthält mehrere TJsonObject, welche nur eine TJsonObject "article" enthalten.

Im Endeffekt gibt es zwei Möglichkeiten:
  1. Du bildest die ganzen Dinge wie z.B. "article" als Delphi-Objekt ab und lässt dir den gesamten Kram als Delphi-Struktur deserialisieren
  2. Dich interessiert nur etwas wie z.B. "Gib mir einfach nur alle Artikelnamen" und holst dir mit dem Weg des geringsten Widerstandes auf direktem Wege ebendiese Daten

Das einmal als Beispiel, im Endeffekt wie ein Beitrag weiter oben, nur halt lieber mit einem "Path" anstatt mit Zwischen-Variablen:

Delphi-Quellcode:
program Project1;

uses System.SysUtils, System.JSON;

const
   JSON = '{ ... }';
var
   jsonObj: TJsonObject;
begin
   jsonObj := TJSONObject.ParseJSONValue(JSON) as TJsonObject;

   var count := jsonObj.GetValue<TJsonArray>('data').Count;
   WriteLn('Wir haben ', count, ' Einträge');

   for var index := 0 to Pred(count) do
    begin
      var path := String.Format('data[%d].article.name', [index]);
      var articleName := jsonObj.GetValue<String>(path);
      WriteLn('Artikel: ', articleName);
    end;

   ReadLn;
end.

stifflersmom 26. Jun 2022 11:45

AW: JSON iterieren, aber wie?
 
@Daddy: Funktioniert! Danke dafür.
@Günther: Funktioniert auch! Danke dafür.
@Maliko: Den Blogpost von Uwe werde ich versuchen umzusetzen bzw. zu verstehen.

Vielen Dank für Eure Bemühungen.

Pfaffe 25. Sep 2022 21:43

AW: JSON iterieren, aber wie?
 
Wie lese ich denn das aus?
"length": [
0,
"mm"
].
Sowas verstehe ich:
"important_information": {
"hazard_warnings": null
}
subobj_important_information := (subobj as TJSONObject).Values['important_information'] as TJSONObject;
Memo1.Lines.Add(subobj_important_information.Value s['hazard_warnings'].Value);

himitsu 25. Sep 2022 23:12

AW: JSON iterieren, aber wie?
 
Die [] ist ein Delphi-Referenz durchsuchenTJSONArray,
und {} ein TJSONObject.

Über .P['abc'] kann man aber auch einen ganzen Pfad angeben (ähnlich dem Bei Google suchenXPath von XML)
Ich weiß, die Hilfe Delphi-Referenz durchsuchenTJSONObject.P ist wieder mal unterirdisch,
https://docwiki.embarcadero.com/Libr...N.TJSONValue.P
aber hier mal was aus den Sourcen.

https://docwiki.embarcadero.com/Libr...er#Description
Code:
  /// <summary> Parses a JSON path with names and indexes.</summary>
  /// <remarks>
  ///  The syntax to write paths is similar to XPath but in a Json way.
  ///  The following XPath expression:
  ///    /entities/urls[0]/indices[1]
  ///  would look like
  ///    entities.urls[0].indices[1]  (dot notation)
  ///  or
  ///    entities["urls"][0]["indices"][1]  (bracket notation)
  ///
  ///  The dot (.) token is used to access the object elements:
  ///    ex: object.key
  ///
  ///  The bracket ([]) token is used to access array or object elements:
  ///    In array: cities[0]
  ///    In object: city["name"] or city['name']
  ///    In object: ["city"]["name"] or ['city']['name']
  ///
  ///  The quote (" or ') is used to introduce a literal when the element is being written in bracket notation:
  ///    ex:["first"]["second"] or ['first']['second']
  ///
  ///  To escape the quote in a literal use backslash (\): \"
  ///    ex: ["quotes(\").should.be.escaped"] or ['quotes(\').should.be.escaped']
  ///
  ///  Note: The backslash will only escape quotes within a literal. Bracket notation can be useful when
  ///  names can not be written in dot notation, like the objects keys with dot characters:
  ///    ex: object["key.with.dots"] or object['key.with.dots']
  ///
  /// </remarks>
  TJSONPathParser = record

Pfaffe 26. Sep 2022 07:26

AW: JSON iterieren, aber wie?
 
So gehts:
Delphi-Quellcode:
// subobj: TJSONObject;
subobj_dimensions := subobj.Values['dimensions'] as TJSONObject;
var subobj_length := subobj_dimensions.Values['length'] as TJSONArray;
Memo1.Lines.Add('length = ' + subobj_length.Items[0].Value + ' ' + subobj_length.Items[1].Value);
var subobj_width := subobj_dimensions.Values['width'] as TJSONArray;
Memo1.Lines.Add('width = ' + subobj_width.Items[0].Value + ' ' + subobj_width.Items[1].Value);
var subobj_height := subobj_dimensions.Values['height'] as TJSONArray;
Memo1.Lines.Add('height = ' + subobj_height.Items[0].Value + ' ' + subobj_height.Items[1].Value);

Incocnito 26. Sep 2022 08:49

AW: JSON iterieren, aber wie?
 
Zitat:

Zitat von Pfaffe (Beitrag 1512430)
Wie lese ich denn das aus?
"length": [
0,
"mm"
].
Sowas verstehe ich:
"important_information": {
"hazard_warnings": null
}...

Oha, das hatte ich gar nicht gesehen. Wenn man sowas als Klasse (für TJson.JsonToObject<TMyClass>(sValue)) abbilden will, wie soll das denn gehen?
Mit Variant?
Delphi-Quellcode:
type TWhatever_DimVals = Array of Variant;

type
  TWhatever_Dimensions : class
  private
    FLength : TWhatever_DimVals;
    FWidth : TWhatever_DimVals;
    FHeight : TWhatever_DimVals;
  public
    ....
  end;
Das fände ich jetzt aber auch nicht so geil.

LG Incocnito

mytbo 26. Sep 2022 21:41

AW: JSON iterieren, aber wie?
 
Zitat:

Zitat von Pfaffe (Beitrag 1512430)
Wie lese ich denn das aus?
"length": [
0,
"mm"
]

Mit Hilfe von mORMot lassen sich einzelne Wert auslesen, oder die gesamte Struktur als Objekt/Record abbilden.

Der Zugriff auf einzelne Werte erfolgt so:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.text,
  mormot.core.variants;

var
  doc: TDocVariantData;
  item: PDocVariantData;
  itemDim: PDocVariantData;
begin
  doc.InitJsonFromFile('data.json', JSON_[mFastFloat]);
  for item in doc.A['data'].Objects do
  begin
    itemDim := item.O['article'].O['dimensions'];
    with itemDim.A['length']^ do
      ShowMessage(Utf8ToString(FormatUtf8('Length: %%', [Value[0], Value[1]])));
  end;
Die JSON Daten als Record abbilden, gelingt so:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.json,
  mormot.core.text,
  mormot.core.os;
 
type
  TDataRec = record
    data: array of record
      article: record
        id: Integer;
        dimensions: record
          length: array of Variant;
          width: array of Variant;
          height: array of Variant;
        end;
      end;
    end;
    meta: record
      pagination: record
        total: Integer;
        count: Integer;
      end;
    end;
  end;

var
  i: Integer;
  rec: TDataRec;
  json: RawJson;
begin
  json := StringFromFile('data.json');
  if RecordLoadJson(rec, json, TypeInfo(TDataRec)) then
  begin
    for i := 0 to High(rec.data) do
    begin
      with rec.data[i].article.dimensions do
        ShowMessage(Utf8ToString(FormatUtf8('Length: %%', [length[0], length[1]])));
    end;
  end;
Die Record Definition muss die JSON Werte nicht vollständig abbilden, wenn zum Einlesen der Mode Tolerant gewählt wird.

Bis bald...
Thomas


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:45 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz