AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Json Array of String: Wie Array-Items per Schleife auslesen

Json Array of String: Wie Array-Items per Schleife auslesen

Ein Thema von juergen · begonnen am 18. Sep 2023 · letzter Beitrag vom 20. Sep 2023
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.163 Beiträge
 
Delphi 11 Alexandria
 
#1

Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 18. Sep 2023, 19:36
Hallo,

mir fällt der Umgang mit Json noch ziemlich schwer. Ich habe 1 String-Array in der Json-Datei.
Folgendes Json (gekürzt).
Code:
{
    "Database": {
        "DB-ServerName": "",
        "DB-Name": "",
        "DB-User": "",
        "DB-User-Pw": 0,
        "DB-Provider": 0
    },
    "ShorthandSymbol": [
        "UxRT",
        "KuZT",
        "KpZR",
        "BFRS",
        "HKJD",
        "UDTR",
        "SI",
        "dgws",
        "DEFdg",
        "EIZ",
        "ITFd"
    ]
}
Ich habe den Json-Dateiinhalt in einem Json-Objekt:
Delphi-Quellcode:
...
VAR
  my_jsonObj: TJSONObject;
BEGIN
 IF FileExists( ExtractFilePath( ParamStr( 0 ) ) + 'Settings.json' ) THEN
    BEGIN
      my_jsonObj := TJSONObject.ParseJSONValue( TFile.ReadAllText( ExtractFilePath( ParamStr( 0 ) ) + 'Settings.json' ) ) AS TJSONObject;
...
Jetzt muss ich irgendwie über eine Schleife (?) die einzelnen Stringwerte aus dem Array auslesen.

Wie komme ich an die einzelnen Json-String-Array-Werte?

Vielen Dank schon mal vorab.
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.862 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 18. Sep 2023, 20:13
Mit my_jsonObj.Values['ShorthandSymbol'] as TJSONArray kommst du schon mal an das Array. Dort kannst du dann einfach über den Index auf die einzelnen Elemente zugreifen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.163 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 18. Sep 2023, 23:06
Vielen Dank, Uwe!

Ich habe jetzt folgende Art einer Lösung:
ShowMessage( ( ( my_jsonObj.Values['ShorthandSymbol'] AS TJSONArray ).Items[1] ).ToString ); Das Ganze scheint zu funktionieren, aber irgendwie fühlt sich das für mich noch nicht richtig an.
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
453 Beiträge
 
#4

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 00:12
Das Ganze scheint zu funktionieren, aber irgendwie fühlt sich das für mich noch nicht richtig an.
Lösung mit mORMot. Wenn die Eigenschaftsnamen in der JSON-Datei nach den Regeln für Pascal Feldnamen benannt sind, lässt es sich automatisch mappen:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.text,
  mormot.core.json,
  mormot.core.os;

type
  TDBSettings = packed record
    DataBase: record
      DBServerName: String; // statt "DB-ServerName"
      DBName: String;
      DBUser: String;
      DBUserPw: Integer;
      DBProvider: Integer;
    end;
    ShorthandSymbol: TStringDynArray; // array of String
    function LoadFromFile(const pmcFileName: TFileName): Boolean;
    procedure SaveToFile(const pmcFileName: TFileName);
  end;

function TDBSettings.LoadFromFile(const pmcFileName: TFileName): Boolean;
begin
  Result := RecordLoadJson(Self, StringFromFile(pmcFileName), TypeInfo(TDBSettings));
end;

procedure TDBSettings.SaveToFile(const pmcFileName: TFileName);
begin
  FileFromString(RecordSaveJson(Self, TypeInfo(TDBSettings)), pmcFileName);
end;
Im Beispiel ist das nicht der Fall, es muss ein Custom-Serializer registriert werden:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.data,
  mormot.core.text,
  mormot.core.json,
  mormot.core.rtti,
  mormot.core.os;

type
  TDBSettingDataBase = class(TObject)
  private
    FDBServerName: String;
    FDBName: String;
    FDBUser: String;
    FDBUserPw: Integer;
    FDBProvider: Integer;
  protected
    class procedure ReadDataBaseJson(var pmvContext: TJsonParserContext; pmValue: TObject);
    class procedure WriteDataBaseJson(pmWriter: TJsonWriter; pmValue: TObject; pmOptions: TTextWriterWriteObjectOptions);
  public
    property DBServerName: String
      read FDBServerName write FDBServerName;
    property DBName: String
      read FDBName write FDBName;
    property DBUser: String
      read FDBUser write FDBUser;
    property DBUserPw: Integer
      read FDBUserPw write FDBUserPw;
    property DBProvider: Integer
      read FDBProvider write FDBProvider;
  end;

  TDBSettings = class(TSynAutoCreateFields)
  private
    FDataBase: TDBSettingDataBase;
    FShorthandSymbol: TStringDynArray;
  public
    function LoadFromFile(const pmcFileName: TFileName): Boolean;
    procedure SaveToFile(const pmcFileName: TFileName);
  published
    property DataBase: TDBSettingDataBase
      read FDataBase;
    property ShorthandSymbol: TStringDynArray
      read FShorthandSymbol;
  end;

class procedure TDBSettingDataBase.ReadDataBaseJson(var pmvContext: TJsonParserContext; pmValue: TObject);
var
  values: array[0..4] of TValuePUtf8Char;
begin
  if pmvContext.ParseObject(['DB-ServerName', 'DB-Name', 'DB-User', 'DB-User-Pw', 'DB-Provider'], @values) then
  begin
    with TDBSettingDataBase(pmValue) do
    begin
      DBServerName := values[0].ToString;
      DBName := values[1].ToString;
      DBUser := values[2].ToString;
      DBUserPw := values[3].ToInteger;
      DBProvider := values[4].ToInteger;
    end;
  end;
end;

class procedure TDBSettingDataBase.WriteDataBaseJson(pmWriter: TJsonWriter; pmValue: TObject; pmOptions: TTextWriterWriteObjectOptions);
begin
  with TDBSettingDataBase(pmValue) do
    pmWriter.AddJsonEscape(['DB-ServerName', DBServerName, 'DB-Name', DBName, 'DB-User', DBUser, 'DB-User-Pw', DBUserPw, 'DB-Provider', DBProvider]);
end;

function TDBSettings.LoadFromFile(const pmcFileName: TFileName): Boolean;
begin
  Result := ObjectLoadJson(Self, StringFromFile(pmcFileName));
end;

procedure TDBSettings.SaveToFile(const pmcFileName: TFileName);
begin
  FileFromString(ObjectToJson(Self), pmcFileName);
end;

initialization
  TRttiJson.RegisterCustomSerializerClass(TDBSettingDataBase, TDBSettingDataBase.ReadDataBaseJson, TDBSettingDataBase.WriteDataBaseJson);
Und so anwenden:
Delphi-Quellcode:
with TDBSettings.Create do
try
  LoadFromFile('settings.json');
  ShowMessage(DataBase.DBServerName);

  DataBase.DBServerName := 'TestServer';
  SaveToFile('settings.json');
finally
  Free;
end;
Bis bald...
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
42.824 Beiträge
 
Delphi 12 Athens
 
#5

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 00:26
Diese JSON-Klassen können auch sowas wie XPath.

https://docwiki.embarcadero.com/Libr...JSONPathParser
https://docwiki.embarcadero.com/Libr...ject.FindValue
...
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
453 Beiträge
 
#6

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 00:39
Diese JSON-Klassen können auch sowas wie XPath.
Etwa so:
Delphi-Quellcode:
var
  doc: TDocVariantData;
begin
  doc.InitJsonFromFile('settings.json');
  ShowMessage(doc.P['DataBase.DB-ServerName']);
Bis bald...
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.163 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 17:53
Zunächst vielen Dank!

@mytbo,
Je länger ich mir das anschaue, desto mehr gefällt es mir!

Ich werde das heute Abend mal mit mORMot angehen.
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
453 Beiträge
 
#8

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 18:37
Ich werde das heute Abend mal mit mORMot angehen.
mORMot gehört zu den qualitativ hochwertigsten Bibliotheken im Pascal Universum. Es sind unzählige Klassen und Funktionen zu finden. Um schnell ein Erfolgserlebnis zu haben, sollte man sich zu Beginn nur auf einen Teilbereich konzentrieren. In deinem Beispiel die JSON Serialisierung. Die Units sind wohl geordnet und strukturell logisch aufgebaut. Wenn man es verstanden hat, fügt sich alles wunderbar zusammen. Nur der Anfang, der ist schwer.

Die mORMot Bibliothek muss nicht installiert werden. Den aktuellen Commit und die static binaries aus dem letzten Tag herunterladen. In Delphi die entsprechenden Bibliotheks- und Suchpfade setzen. Beim Erstellen hilft dieses Muster:
Code:
// Die Doppelpunkte einfach durch den Speicherpfad ersetzten
..\src;..\src\app;..\src\core;..\src\crypt;..\src\db;..\src\lib;..\src\misc;..\src\net;..\src\orm;..\src\rest;..\src\script;..\src\soa;..\src\tools\ecc;..\src\ui;
Die aktuelle Entwicklung ist mORMot2. mORMot ist gut dokumentiert. Die Hilfe bezieht sich noch auf mORMot1. Die Namen für Klassen und Funktionen können sich leicht unterscheiden. Sie umfasst mehr als 2500 Seiten. Davon enthalten die ersten ca. 650 Seiten einen sehr lesenswerten allgemeinen Teil, der Rest ist API Dokumentation.

Bis bald...
Thomas
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
453 Beiträge
 
#9

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 19:43
Um das Ganze abzuschließen, im konkreten Fall würde es reichen, die Eigenschaftsnamen für das Lesen und Schreiben der JSON-Datei zu ändern:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.data,
  mormot.core.text,
  mormot.core.json,
  mormot.core.rtti,
  mormot.core.unicode,
  mormot.core.variants,
  mormot.core.os;
  
type
  TDBSettingDataBase = class(TSynPersistent)
  private
    FDBServerName: String;
    FDBName: String;
    FDBUser: String;
    FDBUserPw: Integer;
    FDBProvider: Integer;
  published
    property DBServerName: String
      read FDBServerName write FDBServerName;
    property DBName: String
      read FDBName write FDBName;
    property DBUser: String
      read FDBUser write FDBUser;
    property DBUserPw: Integer
      read FDBUserPw write FDBUserPw;
    property DBProvider: Integer
      read FDBProvider write FDBProvider;
  end;
  
  TDBSettings = class(TSynAutoCreateFields)
  private
    FDataBase: TDBSettingDataBase;
    FShorthandSymbol: TStringDynArray;
  public
    function LoadFromFile(const pmcFileName: TFileName): Boolean;
    procedure SaveToFile(const pmcFileName: TFileName);
  published
    property DataBase: TDBSettingDataBase
      read FDataBase;
    property ShorthandSymbol: TStringDynArray
      read FShorthandSymbol;
  end;

function TDBSettings.LoadFromFile(const pmcFileName: TFileName): Boolean;
begin
  Result := ObjectLoadJson(Self, StringFromFile(pmcFileName));
end;

procedure TDBSettings.SaveToFile(const pmcFileName: TFileName);
begin
  FileFromString(ObjectToJson(Self), pmcFileName);
end;
  
initialization
  Rtti.ByClass[TDBSettingDataBase].Props.NameChanges(
    ['DBServerName', 'DBName', 'DBUser', 'DBUserPw', 'DBProvider'],
    ['DB-ServerName', 'DB-Name', 'DB-User', 'DB-User-Pw', 'DB-Provider']);
Als Ausführung mit Records wie folgt:
Delphi-Quellcode:
type
  TDBSettingDataBase = packed record
    DBServerName: String;
    DBName: String;
    DBUser: String;
    DBUserPw: Integer;
    DBProvider: Integer;
  end;

  TDBSettings = packed record
    DataBase: TDBSettingDataBase;
    ShorthandSymbol: TStringDynArray; // array of String
    function LoadFromFile(const pmcFileName: TFileName): Boolean;
    procedure SaveToFile(const pmcFileName: TFileName);
  end;

function TDBSettings.LoadFromFile(const pmcFileName: TFileName): Boolean;
begin
  Result := RecordLoadJson(Self, StringFromFile(pmcFileName), TypeInfo(TDBSettings));
end;

procedure TDBSettings.SaveToFile(const pmcFileName: TFileName);
begin
  FileFromString(RecordSaveJson(Self, TypeInfo(TDBSettings)), pmcFileName);
end;

initialization
  Rtti.ByTypeInfo[TypeInfo(TDBSettingDataBase)].Props.NameChanges(
    ['DBServerName', 'DBName', 'DBUser', 'DBUserPw', 'DBProvider'],
    ['DB-ServerName', 'DB-Name', 'DB-User', 'DB-User-Pw', 'DB-Provider']);
Anwendung so:
Delphi-Quellcode:
var
  rec: TDBSettings;
begin
  rec.LoadFromFile('settings.json');
  ShowMessage(rec.DataBase.DBServerName);

  rec.DataBase.DBServerName := 'TestServer';
  rec.SaveToFile('settings.json');
Bis bald...
Thomas

Geändert von mytbo (19. Sep 2023 um 19:53 Uhr) Grund: Tippfehler korrigiert
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.862 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Json Array of String: Wie Array-Items per Schleife auslesen

  Alt 19. Sep 2023, 21:43
Diesen Ansatz mit dem JSON-Class-Mapping kann man auch ohne externe Bibliothek nur mit Delphi-Bordmitteln realisieren:
Delphi-Quellcode:

interface

uses
  System.Types,
  REST.Json.Types; // wegen des Attributs

type
  TDBSettings = class
  type
    TDataBase = class
    private
      [JSONName('DB-Name')]
      FDBName: String;
      [JSONName('DB-Provider')]
      FDBProvider: Integer;
      FDBServerName: String;
      [JSONName('DB-User')]
      FDBUser: String;
      [JSONName('DB-User-Pw')]
      FDBUserPw: Integer;
    public
      property DBName: String read FDBName write FDBName;
      property DBProvider: Integer read FDBProvider write FDBProvider;
      property DBServerName: String read FDBServerName write FDBServerName;
      property DBUser: String read FDBUser write FDBUser;
      property DBUserPw: Integer read FDBUserPw write FDBUserPw;
    end;
  private
    FDatabase: TDataBase;
  public
    ShorthandSymbol: TStringDynArray;
    constructor Create;
    destructor Destroy; override;
    class function LoadFromFile(const pmcFileName: string): TDBSettings;
    procedure SaveToFile(const pmcFileName: string);
    property Database: TDataBase read FDatabase;
  end;

implementation

constructor TDBSettings.Create;
begin
  inherited Create;
  FDatabase := TDataBase.Create();
end;

destructor TDBSettings.Destroy;
begin
  FDatabase.Free;
  inherited Destroy;
end;
In der Anwendung sieht das dann in etwa so aus:
Delphi-Quellcode:
uses
  System.IOUtils, System.SysUtils,
  REST.Json;

const
  cFileName = 'c:\temp\settings.json';

begin
  var settings := TJson.JsonToObject<TDBSettings>(string.Join(sLineBreak, cArr));
  try
    TFile.WriteAllText(cFileName, TJson.ObjectToJsonString(settings));
  finally
    settings.Free;
  end;

begin
  var settings := TJson.JsonToObject<TDBSettings>(TFile.ReadAllText(cFileName));
  try
    ...
  finally
    settings.Free;
  end;
end;
Nebenbei: Das StringArray als Feld anstatt Property ist zumindest zu hinterfragen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 Uhr.
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