Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TJSONObjectBuilder keine leeren Objekte/Arrays (https://www.delphipraxis.net/194359-tjsonobjectbuilder-keine-leeren-objekte-arrays.html)

Zacherl 11. Nov 2017 16:34


TJSONObjectBuilder keine leeren Objekte/Arrays
 
Hallo zusammen,

ich schaue mir grade das
Delphi-Quellcode:
System.JSON.Builders
Framework an. Rufe ich dort:
Delphi-Quellcode:
Builder
  .BeginObject
    .BeginObject('test')
    .EndObject
  .EndObject
auf, dann erhalte ich als Output:
Code:
{
  "test": {}
}
also ein leeres Objekt namens "test".

Macht soweit natürlich Sinn. Meine Frage jetzt aber trotzdem:
:?: Ist es möglich die Objekte/Arrays erst dann zu schreiben, wenn sie mindestens ein eigenes Feld besitzen?

Hintergrund ist, dass ich eine Hierachie von Klassen serialisieren will. Jede Klasse besitzt eine
Delphi-Quellcode:
Serialize
Methode, der ich eine Builder Instanz und den Feldnamen übergeben will. Die Instanz soll sich dann selbstständig serialisieren. Jetzt kann es passieren, dass alle Felder der Instanz die Standardwerte besitzen. In diesem Falle sollen die Felder nicht im JSON erscheinen.
Ich würde nun gerne weiterhin die Felder nach und nach prüfen, also:
Delphi-Quellcode:
Builder.BeginObject(FieldName);
if (Field1 <> Default1) then Builder.Add('field1', Field1);
if (Field2 <> Default2) then Builder.Add('field2', Field2);
..
Builder.EndObject;
Ist sowas mit dem
Delphi-Quellcode:
System.JSON.Builders
Framework möglich, oder müsste ich tatsächlich vor dem
Delphi-Quellcode:
BeginObject
erstmal alle Felder auf Standardwerte prüfen?

Viele Grüße
Zacherl

himitsu 11. Nov 2017 18:31

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
BeginObject erstellt ein neues Objekt
und Objekte ohne Eigenschaften sind natürlich möglich.

Also vorher prüfen oder nachher das Objekt wieder löschen. :roll:

Zacherl 11. Nov 2017 18:43

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Zitat:

Zitat von himitsu (Beitrag 1386022)
Also vorher prüfen oder nachher das Objekt wieder löschen. :roll:

Vorher alle Felder prüfen ist ja genau das, was ich nicht will. Dann habe ich alle Checks doppelt:
Delphi-Quellcode:
if (Field1 <> Default1) and (Field2 <> Default2) and ... then
begin
  Builder.BeginObject(FieldName);
  if (Field1 <> Default1) then Builder.Add('field1', Field1);
  if (Field2 <> Default2) then Builder.Add('field2', Field2);
  ..
  Builder.EndObject;
end;
Objekt nachher löschen: Sicherlich. Im Builder selbst habe ich dafür allerdings keine entsprechenden Methoden gefunden. Einziges Workaround, was mir im Moment vorschwebt, ist es vor dem
Delphi-Quellcode:
Builder.BeginObject(FieldName)
die Position von
Delphi-Quellcode:
TStreamWriter(Builder.Writer).BaseStream
zu sichern und nach dem
Delphi-Quellcode:
Builder.EndObject
zu schauen, ob die Position mehr als 2 Bytes erhöht wurde. Dann könnte ich das leere Objekt über
Delphi-Quellcode:
Stream.Position -= 2
wieder löschen. Schön ist aber anders.

himitsu 11. Nov 2017 20:01

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Delphi-Quellcode:
if (Field <> Default) then Builder.Add('field', Field);

in eine Methode auslagern, da prüfen und wenn True, vorher schauen, ob das Objekt angelegt wurde und wenn nicht, dann das BeginObject und danach das Add :zwinker:
Am Ende auch nur das EndObject, wenn das Objekt existiert.

Der schöne Günther 11. Nov 2017 20:14

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Eine Frage die garantiert nicht weiterhilft: Ist das denn schlimm wenn da ein "leeres Objekt" ist? Als Mensch hätte ich direkt gesehen "Ja, 'test' ist belegt und darin ist nichts besonderes mehr das vom Standard abweicht".

Zacherl 12. Nov 2017 06:28

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Zitat:

Zitat von himitsu (Beitrag 1386029)
Delphi-Quellcode:
if (Field <> Default) then Builder.Add('field', Field);

in eine Methode auslagern, da prüfen und wenn True, vorher schauen, ob das Objekt angelegt wurde und wenn nicht, dann das BeginObject und danach das Add :zwinker:
Am Ende auch nur das EndObject, wenn das Objekt existiert.

Ja, so ähnlich hatte ich die Funktionalität in meinem eigenen "Builder Framework" implementiert (als es das noch nicht in der RTL gab). Vermutlich die bessere Alternative zu dem Stream Gewusel :)

Zitat:

Zitat von Der schöne Günther (Beitrag 1386030)
Eine Frage die garantiert nicht weiterhilft: Ist das denn schlimm wenn da ein "leeres Objekt" ist? Als Mensch hätte ich direkt gesehen "Ja, 'test' ist belegt und darin ist nichts besonderes mehr das vom Standard abweicht".

Schlimm nicht, bloß möchte ich das Format bewusst möglichst gut lesbar gestalten. Konkret handelt es sich um diese Datei:
https://github.com/zyantific/zydis-d...tructions.json

Jede einzelne Instruction kann z.b. bis zu 10 Operanden besitzen. Wenn ich da jetzt für jeden möglichen Eintrag ein leeres Objekt anlege, kann das doch ziemlich schnell unübersichtlich werden.

Fritzew 12. Nov 2017 08:11

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Wir hatten ein ähnliches Problem, allerdings mehr "allgemein" zum feststellen ob ein Object modifiziert wurde.
Die Lösung bei uns war konsequent für alle properties Setter zu verwenden.

aka :
Delphi-Quellcode:
procedure setProperty1(const Value : integer);
begin
 if Value <> fProperty1 then
 begin
  fproperty1 := Value;
   // Call do set the modifiedFlag
   domodified;
 end;
end;
So können wir im Source einfach testen:

Delphi-Quellcode:
if Obj.modified then .......
Hat sich bewährt kommt aber wohl auf den Anwendungsfall an...

Zacherl 12. Nov 2017 17:45

AW: TJSONObjectBuilder keine leeren Objekte/Arrays
 
Zitat:

Zitat von Fritzew (Beitrag 1386048)
Wir hatten ein ähnliches Problem, allerdings mehr "allgemein" zum feststellen ob ein Object modifiziert wurde.
Die Lösung bei uns war konsequent für alle properties Setter zu verwenden.

Setter für alle Properties und ein
Delphi-Quellcode:
Changed
Event besitzen meine Klassen sogar schon. Ist leider für meinen speziellen Fall nicht die beste Lösung, da durch eine Modifikation der Wert einer Property ja auch wieder auf den Standardwert gesetzt werden könnte. Das hieße, dass ich den Check lediglich in die Setter auslagern würde und dann noch einen internen Counter bräuchte, der bei
Delphi-Quellcode:
Property <> Default
inkrementiert und bei
Delphi-Quellcode:
Property = Default
wieder dekrementiert wird (
Delphi-Quellcode:
Counter = 0 <=> Objekt hat nur Default Properties
).

Zitat:

Zitat von himitsu (Beitrag 1386029)
Delphi-Quellcode:
if (Field <> Default) then Builder.Add('field', Field);

in eine Methode auslagern, da prüfen und wenn True, vorher schauen, ob das Objekt angelegt wurde und wenn nicht, dann das BeginObject und danach das Add :zwinker:
Am Ende auch nur das EndObject, wenn das Objekt existiert.

Werde jetzt mal schauen, ob sich das generisch - und trotzdem performant - umsetzen lässt, ohne für jeden Datentyp eine extra Funktion erstellen zu müssen.


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