AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

JSON richtig parsen

Ein Thema von Hobbycoder · begonnen am 23. Mär 2017 · letzter Beitrag vom 25. Mär 2017
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.203 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

AW: JSON richtig parsen

  Alt 23. Mär 2017, 10:32
Du machst es dir viel zu kompliziert - Das ist alles schon fertig: Mit TJson.JsonToObject<TErrorMessage>(yourJsonObject) hast du eine automatische Umwandlung deines Json-Objekts in TErrorMessage.

Hier als Beispiel:

Delphi-Quellcode:
// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
// JCL_DEBUG_EXPERT_INSERTJDBG OFF
// JCL_DEBUG_EXPERT_DELETEMAPFILE OFF
program Project19;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.IoUtils,
  System.Json,
  Rest.Json,
  Unit10 in 'Unit10.pas';


const
   filePath = 'y:\jsonTest.txt';

procedure parseJson();
var
   fileContent:       String;
   messagesJson:      TJSONArray;
   messageJson:      TJSONValue;

   messageObject:      TErrorMessage;
   messagesObjects:   TArray<TErrorMessage>;
begin
   fileContent := TFile.ReadAllText(filePath);

   messagesJson := TJSONObject.ParseJSONValue(fileContent) as TJSONArray;

   messagesObjects := [];
   for messageJson in messagesJson do begin
      messageObject := TJson.JsonToObject<TErrorMessage>(messageJson as TJsonObject);
      messagesObjects := messagesObjects + [messageObject];
   end;

   readln;
end;

begin
   parseJson();
end.

PS: Ja, die Umwandlung stammt aus Rest.Json.pas die beim RAD-Studio dabei ist. Ich wundere mich auch, was das mit REST zu tun haben soll, warum das nicht auch in System.Json.pas steckt. Aber das ist hoffentlich kein Stolperstrick?
Angehängte Grafiken
Dateityp: png Unbenannt.png (20,1 KB, 223x aufgerufen)
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#2

AW: JSON richtig parsen

  Alt 23. Mär 2017, 11:55
Danke Das funktioniert ja wie geschnitten Brot

Zu meinem Verständnis: Die Voraussetzungen sind, nehme ich mal an, dass a) der JSON-String NUR ein Array enthält, und b) die Bezeichner für die Values innerhalb des Array den Properties des Objekts entsprechen?
Wie findet die Funktion denn die passenden Properties? Und werden die Typen immer passend umgewandelt (String, Int, TDatetime, etc)?
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.203 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: JSON richtig parsen

  Alt 23. Mär 2017, 12:03
Zu a)

Ja - Eigentlich musst du ja im Voraus wissen, was du bekommst. Ob es ein Array mit X Dingen drin ist, oder nur ein Ding. Wenn beides auftreten kann muss dein Code mit beiden Wegen zurechtkommen. Oder meinst du dass der "richtige" Inhalt wiederum ein Objekt mit einer Handvoll Feldern und ein Feld ist dieses Array? Auch das ist kein Problem, man muss es nur abbilden im Code.


Zu b)
Das Umwandeln des Json in dein TErrorMessage-Objekt fasst die Properties nicht an. Das siehst du wenn du z.B. einen Haltepunkt in deine Setter-Methode setzt. Der "Marshaller" erstellt zuerst ein TErrorMessage-Objekt, dann sucht er sich für jedes JSON-Feld das passende Feld in deinem Delphi-Objekt und steckt den Wert da hinein. Da der JSON-String den du angegeben hast anscheinend einwandfrei war, klappt das auch mit Dingen wie TDateTime (wie man sieht).

Eine Besonderheit: In deinem Fall hat das so toll geklappt weil du dieser merkwürdigen Konvention (bzw. oft leider Notwendigkeit) folgst allen Feldnamen immer ein "F" voran zu stellen. In deinem Json-String ist das nicht so. Trotzdem hat das geklappt. Warum das so ist steht hier:
http://www.delphipraxis.net/182105-f...unmarshal.html

Ich rege mich darüber eher auf, aber im verlinkten Thema steht auch wie du z.B. die Felder in deiner Klasse auch anders nennen kannst als im JSON und der Mechanismus trotzdem weiterhin funktionieren kann.
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#4

AW: JSON richtig parsen

  Alt 23. Mär 2017, 12:33
Den verlinkten Artikel habe ich gelesen.

Demnach scheint, auch wenn du keine Freund davon bist, eine einheitliche Namenskonvention zwischen json und objekt für die geringsten Komplikationen zu sorgen. Damit kann ich leben.
Mein Objekt umfasst ja mehr Properties, als im Json übermittelt. Du Funktion hat damit keine Probleme.
Was aber passiert im umgekehrten Fall? Kommt eine Exception, oder ignoriert die Funktion das dann einfach? Das könnte ja schnell passieren, denn nicht immer hat man selbst Einfluss auf den JSON-String bzw. wann der mal verändert wird.
(Ich könnt's auch ausprobieren, aber vielleicht weißt du das auch so.)
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#5

AW: JSON richtig parsen

  Alt 23. Mär 2017, 12:42
Und ein Problem hab ich dann doch noch.
Ich habe ja 2 Properties als enumeration type.
Delphi-Quellcode:
  TEMStatus=(emsNeu, emsIB, emsKorr, emsGepr);
  TEMDringlichkeit=(emdLowest, emdLower, emdNormal, emdHigh, emdHighest);

  property Status: TEMStatus read FStatus write SetStatus;
  property Dringlichkeit: TEMDringlichkeit read FDringlichkeit write SetDringlichkeit;
Das würde ich auch gerne so belassen.

Diese werden von TJson.JsonToObject<TErrorMessage>(messageJson as TJsonObject) nicht korrect gesetzt. Wahrscheinlich eher gar nicht, da json selbst diese Datentypen nicht kennt.
Da ich sie auch nicht im Create vordefiniere, bleiben sie ohne wert und können bei der späteren Verwendung auch nicht korrekt gecastet werden.

Wie löst man sowas? Im JSON sind die ja als Integer drin.
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.203 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: JSON richtig parsen

  Alt 23. Mär 2017, 17:54
Zu 1)
Ich habe es nicht im Kopf, aber durch Ausprobieren sieht man meine ich dass er weder auf die Nase fällt wenn dein Objekt mehr Felder hat als das Json, noch umgekehrt wenn das Json mehr Felder hat als dein Objekt. Eigentlich ist dir ja klar was du als Json bekommst. Das ist doch ein perfekter Kandidat für Unit-Tests. Sollte sich der Json-Mechanismus in Delphi eines Tages ändern würdest du das mit deinen Tests ja sofort merken wenn dort etwas nicht mehr stimmt

Zu 2)
Enumemerationen sind jetzt etwas kniffelig. Denn in JSON gibt es so etwas nicht. Deine Gegenstelle legt die jetzt als Integer ab sagst du. Hätte man auch als Strings machen können. Ich sehe zwei Möglichkeiten:
  1. Einen eigenen JSON-Interceptor bauen
  2. Die billige Lösung

Der Interceptor würde die Zahl aus deinem Json auswerten können und wieder auf deinen Enum-Typen zurückführen können. Ich finde hier im Forum einmal etwas dazu, bekomme es selbst aber auf die Schnelle nicht mehr hin.

Ich finde es auch in dem Fall einen Overkill. Im Fall Enum/Zahl - ganz ehrlich - Warum nicht einfach die Felder in deinem Objekt auch als Zahl (z.B. Byte) machen und die Getter & Property anpassen? Zu irgend etwas müssen diese Getter ja gut sein


Delphi-Quellcode:
type
   TEMStatus=(emsNeu, emsIB, emsKorr, emsGepr);

   TEMDringlichkeit=(emdLowest, emdLower, emdNormal, emdHigh, emdHighest);

   TErrorMessage = class
      private var
         FStatus:      Byte;
         FDringlichkeit:   Byte;
      private
         function getStatus(): TEMStatus;
         function getDringlicheit: TEMDringlichkeit;
      public
         property Status: TEMStatus read getStatus;
         property Dringlichkeit: TEMDringlichkeit read getDringlicheit;
   end;


implementation

{ TErrorMessage }

function TErrorMessage.getDringlicheit(): TEMDringlichkeit;
begin
   Result := TEMDringlichkeit(FDringlichkeit);
end;

function TErrorMessage.getStatus(): TEMStatus;
begin
   Result := TEMStatus(FStatus);
end;
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.740 Beiträge
 
Delphi 6 Enterprise
 
#7

AW: JSON richtig parsen

  Alt 24. Mär 2017, 08:02
Warum kann man eigentlich Properties nicht überladen? Das wäre doch jetzt echt praktisch für diesen Fall.
Ralph
  Mit Zitat antworten Zitat
Antwort Antwort


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 16:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz