Einzelnen Beitrag anzeigen

Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
659 Beiträge
 
Delphi 12 Athens
 
#1

Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

  Alt 20. Feb 2019, 10:05
Hallo zusammen,

zur Kommunikation zwischen einem Server und einem Client nutze ich an diversen Stellen JSON. Der Code, um irgendeine Info als JSON-String zu erzeugen, sah dabei meistens in etwa so aus:
Delphi-Quellcode:
function TmyClass.GetInfoAsJSON: string;

var
  jWriter: TJsonTextWriter;

begin
  jWriter:=TJsonTextWriter.Create(TStringWriter.Create);
  try
    jWriter.WriteStartObject;
    jWriter.WritePropertyName('values');
    jWriter.WriteValue('wuppdi');
    jWriter.WriteEndObject;
    Result:=jWriter.Writer.ToString;
  finally
    jWriter.Writer.Free;
    jWriter.Free;
  end;
end;
(natürlich sind die erzeugten JSON-Strukturen normalerweise etwas komplexer )

Funktioniert auch soweit, dachte ich zumindest. Im Client kam immer gültiges JSON an und konnte dort problemlos verarbeitet werden. Nachdem ich das jetzt schon einige Zeit so nutze, habe ich aber gestern gemerkt, dass der Server ab und zu mit einer AV abschmiert. Nach diversen grauen Haaren mehr kam ich dann darauf, dass die Ursache tatsächlich das Freigeben des "jWriter" ist, also der Aufruf "jWriter.Free".

Ursache ist, dass innerhalb des Destroy vom TJSONTextWriter noch einmal auf den TextWriter innerhalb des JSONTextWriter zugegriffen wird, also auf TJSONTextWriter.FWriter. Nur: den habe ich ja schon in der Zeile dadrüber mit "jWriter.Writer.Free" freigegeben - muss ja auch weg. Die Lösung ist also, dass man sich diesen inneren TextWriter entweder beim Erzeugen oder beim Freigeben in einer eigenen Variablen merkt.

Der Code sieht dann also so aus:
Delphi-Quellcode:
function TmyClass.GetInfoAsJSON: string;

var
  jWriter: TJsonTextWriter;
  textWriter: TTextWriter;

begin
  jWriter:=TJsonTextWriter.Create(TStringWriter.Create);
  try
    jWriter.WriteStartObject;
    jWriter.WritePropertyName('values');
    jWriter.WriteValue('wuppdi');
    jWriter.WriteEndObject;
    Result:=jWriter.Writer.ToString;
  finally
    textWriter:=jWriter.Writer;
    jWriter.Free;
    textWriter.Free;
  end;
end;
Wie gesagt, man kann sich den TextWriter natürlich auch oben beim Create merken - ich hab es jetzt beim Freigeben gemacht, um das Erezugen und Freigeben dann leichter in zwei kleine Hilfsfunktionen auslagern zu können. So funktioniert jetzt auch alles wieder ohne Zugriffsverletzung.

Mir kommt das aber irgendwie alles ziemlich umständlich vor. Obwohl ich schon in Delphi gesucht und nichts anderes gefunden habe und ich mir daher ziemlich sicher bin, das richtig zu nutzen, dennoch mal die Frage: mir kommt das sehr merkwürdig vor, dass man so viele Zeilen braucht, um das Ding ordentlich zu erzeugen und freizugeben. Ist das wirklich so gedacht oder übersehe ich da irgendwo eine viel einfachere Struktur, die man eigentlich benutzen sollte?

Falls das alles tatsächlich so gedacht ist, dann möge dieser Post zukünftigen Lesern zumindest als Hilfe dienen, nicht über den gleichen Fehler zu stolpern. Und vielleicht wäre es ja eine Idee, dass man dem TJSONTextWriter beim Create mitgeben könnte, dass er der Owner vom inneren Writer ist, dann könnte er das Dingen beim Zerstören selber in der richtigen Reihenfolge freigeben und man hätte das ganze Generve nicht.
  Mit Zitat antworten Zitat