Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Wie aus diesem JSON object erstellen? (https://www.delphipraxis.net/204278-wie-aus-diesem-json-object-erstellen.html)

Hobbycoder 14. Mai 2020 08:11


Wie aus diesem JSON object erstellen?
 
Der Titel ist recht allgemein, aber ich weiß nicht wirklich wie ich das betiteln soll.

Gegeben ist folgender JSON-String:
Code:
[
   {
      "id":1,
      "attributes":{
         "notificationTokens":"bliblablup", //<-----
         "color.background":"#yellow"       //<-----
      },
      "name":"admin",
      "login":"",
      "email":"admin",
   },
   {
      "id":4,
      "attributes":{
         "notificationTokens":"bliblablup", //<-----
         "enabled":true //<-----
      },
      "name":"user1",
      "login":"",
      "email":"user1@hotmail.de",
   },
   {
      "id":5,
      "attributes":{
                                             //<-----
      },
      "name":"user2",
      "login":"",
      "email":"user2@hotmail.de",
   }
]
Im Grunde ist das ja ein Array. Das läßt sich in einer TList "TUsers" halten.
Die Klassenstructur könnte so aussehen:
Delphi-Quellcode:
  TUser=class
    property id: Integer;
    property attributes: ??;    //<--Hier weiß ich nicht was ich nehmen soll.
    property name: string;
    property login: string;
    proeprty email: string;
  end;
mein Problem sind die "attributes". Ich weiß nicht was ich da nehmen soll, beziehungsweise wie ich das geschickt parsen kann (idealerwiese sollte das in beide Richtungen gehen (JSON->Object und Object->json). Es können unterschiedliche Datentypen enthalten sein (Integer, string, boolean), unterschiedliche Anzahl der attributes oder auch leer, wie im Beispiel.
Und es ist kein Array, sondern, wo wie ich das erkenne, nur ein Object.
Wie könnt man das behandeln? Oder kann ich das nur zu Fuß machen.

Der schöne Günther 14. Mai 2020 08:28

AW: Wie aus diesem JSON object erstellen?
 
Du hast dir deine Antwort doch schon selbst gegeben, es ist ein Objekt.

Die in der Delphi RTL vorhandene JSON-Serialisierung geht auf die Felder, nicht auf die Properties. Außerdem setzt sie zwingend voraus dass jeder Mensch die Namen der Felder immer mit einem F beginnt. Tust du das nicht, funktioniert es nicht. Oder man sagt explizit mit einem Attribut dass man es ernst meint.

Delphi-Quellcode:
unit Unit1;

interface uses Rest.JSON.Types;

type
   TUserAttributes = class
      [JSONName('notificationTokens')]
      notificationTokens: String;
      [JSONName('color.background')]
      color_background: String;
   end;

   TUser = class
      [JSONName('id')]
      id: Integer;
      [JSONName('attributes')]
      attributes: TUserAttributes;
      [JSONName('name')]
      name: string;
      [JSONName('login')]
      login: string;
      [JSONName('email')]
      email: string;

      constructor Create();
      destructor Destroy(); override;
   end;

implementation

constructor TUser.Create();
begin
   inherited;
   attributes := TUserAttributes.Create();
end;

destructor TUser.Destroy();
begin
   attributes.Free();
   inherited;
end;

end.


Das lässt sich herrlich hin- und her konvertieren:

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.JSON,
  Rest.Json,
  Unit1 in 'Unit1.pas';

const
   input =
      '  {'+
      '     "id":1,'+
      '     "attributes":{'+
      '        "notificationTokens":"bliblablup",'+
      '        "color.background":"#yellow"'+
      '     },'+
      '     "name":"admin",'+
      '     "login":"",'+
      '     "email":"admin"'+
      '  }';
var
   user: TUser;
   asJsonObject: TJsonObject;
begin
   user := TJson.JsonToObject<TUser>(input);
   asJsonObject := TJson.ObjectToJsonObject(user);
   WriteLn( TJson.Format(asJsonObject) );

   readln;
end.

Hobbycoder 14. Mai 2020 08:37

AW: Wie aus diesem JSON object erstellen?
 
ja, du hast recht. Aber vielleicht habe ich mich auch etwas unglücklich ausgedrückt. (Liegt mitunter an der Zeit, die man sich damit beschäftigt)

Ich könnte attributes zu einem einfachen Objekt machen. Nur leider ist das ein Art Property-List, die vom User beliebig erweitert werden kann.
Heute steht da nur:
Code:
      "attributes":{
         "notificationTokens":"bliblablup",
         "color.background":"#yellow"      
      },
morgen kann es dann auch schon so aussehen.
Code:
      "attributes":{
         "notificationTokens":"bliblablup",
         "color.background":"#yellow",    
         "meineSchugroesse":42
      },
Klar kann ich nicht vorhandene Properties ignorieren und bei starrem Objectdesign neue Properties ignorieren. Aber das würde ich gerne nicht tun.

Uwe Raabe 14. Mai 2020 08:41

AW: Wie aus diesem JSON object erstellen?
 
Dann mach doch TUserAttributes mit z.B. einer TStringList als Name-Value Storage und registriere einen eigenen Interceptor, der die Umwandlung aus JSON implementiert.

Hobbycoder 14. Mai 2020 08:43

AW: Wie aus diesem JSON object erstellen?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1464523)
Dann mach doch TUserAttributes mit z.B. einer TStringList als Name-Value Storage und registriere einen eigenen Interceptor, der die Umwandlung aus JSON implementiert.

Tolle Idee. Hab ich noch nie was von gehört. Wie geht denn sowas?

Hobbycoder 14. Mai 2020 08:45

AW: Wie aus diesem JSON object erstellen?
 
Okay, hab was gefunden "REST.Json.Interceptors.TArrayInterceptor"

Auf der Hilfeseite steht natürlich: "Embarcadero Technologies does not currently have any additional information."

Der schöne Günther 14. Mai 2020 08:51

AW: Wie aus diesem JSON object erstellen?
 
Ich versuche auch seit 10 Minuten Doku zu finden wie man einen eigenen Converter/Reverter da reinschraubt, habe jetzt aber ehrlich gesagt auch aufgegeben. Es sollte gehen, aber ich wüsste spontan auch nicht wie.

Hobbycoder 14. Mai 2020 08:56

AW: Wie aus diesem JSON object erstellen?
 
Vielleicht muss ich mir das mal näher ansehen: Synopse mORMot Framework
Ich hab da keinerlei Erfahrung mit. Aber vielleicht läßt es sich damit leichter umsetzen. Normalerweise verwende ich gerne Hausmittel, die, so Gott will, in späteren Version auch noch unterstützt werden.

Uwe Raabe 14. Mai 2020 09:13

AW: Wie aus diesem JSON object erstellen?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1464526)
Ich versuche auch seit 10 Minuten Doku zu finden wie man einen eigenen Converter/Reverter da reinschraubt, habe jetzt aber ehrlich gesagt auch aufgegeben. Es sollte gehen, aber ich wüsste spontan auch nicht wie.

Guckst du hier: Serializing Objects with TJson

stephancramer 15. Jul 2021 07:26

AW: Wie aus diesem JSON object erstellen?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

der Thread ist zwar schon sehr alt, aber ich versuche es trotzdem mal ob ich eine Antwort bekomme.

Bei mir funktioniert das Beispiel von oben nicht. Ich bekommen immer die gleiche Fehlermeldung, siehe Anhang.

Ich habe schon mehrere Beispiele probiert, auch von der Embarcadero-Seite probiert, immer das gleiche.
http://docwiki.embarcadero.com/RADSt...nutzerobjekten

Bin ziemlich an verzweifeln. Objekte zu JSON funktioniert.
Vielleicht kann mir jemand helfen, was ich falsch mache.

Gruß Stephan.

TiGü 15. Jul 2021 08:39

AW: Wie aus diesem JSON object erstellen?
 
Hast du das Beispiel vom schönen Günther aus Beitrag #2 eins zu eins umgesetzt?
Geht bei in 10.4.2 ganz tadellos.

stephancramer 15. Jul 2021 11:28

AW: Wie aus diesem JSON object erstellen?
 
Danke für die schnelle Antwort.

Ja habe ich, erst mit 10.0 und jetzt nochmal mit 10.4.2 (Testversion) als Konsolenanwendung probiert.
Auch das Beispiel von Embarcadero von meinen Link.


Delphi-Quellcode:
class function TJSONUnMarshal.ObjectInstance(Ctx: TRttiContext; TypeName: string): TObject;
var
  rType: TRttiType;
  mType: TRTTIMethod;
  metaClass: TClass;
begin
  [COLOR="Blue"]rType := ObjectType(Ctx, TypeName);[/COLOR]
  if (rType <> nil) then
    for mType in rType.GetMethods do
    begin
      if mType.HasExtendedInfo and mType.IsConstructor then
      begin
        if Length(mType.GetParameters) = 0 then
        begin
          // invoke
          metaClass := rType.AsInstance.MetaclassType;
          Exit(mType.Invoke(metaClass, []).AsObject);
        end;
      end;
    end;
  Exit(nil);
end;
An der blauen Zeile kommt immer nil zurück.

Gruß Stephan

TiGü 15. Jul 2021 11:42

AW: Wie aus diesem JSON object erstellen?
 
Zippe mal dein Projekt und lade es hier als Anhang hoch.

stephancramer 15. Jul 2021 12:09

AW: Wie aus diesem JSON object erstellen?
 
OK, nicht ganz so.

ich hatte TUser in der gleichen Unit, also alles in einer Unit.
Jetzt habe ich TUser in eine eigene Unit ausgelagert und da geht es.

Danke für Deine Hilfe. Ich werde jetzt das Embarcadero Beispiel auch noch so testen, das ich das Objekt
in eine extra Unit auslagere.


Gruß Stephan.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:33 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