AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

Ein Thema von Bbommel · begonnen am 20. Feb 2019 · letzter Beitrag vom 20. Feb 2019
Antwort Antwort
Bbommel

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

Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

  Alt 20. Feb 2019, 09: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
Schokohase
(Gast)

n/a Beiträge
 
#2

AW: Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

  Alt 20. Feb 2019, 09:11
So würde man es ja normalerweise machen:
Delphi-Quellcode:
function TmyClass.GetInfoAsJSON: string;
var
  jWriter: TJsonTextWriter;
  textWriter: TTextWriter;
begin
  textWriter := TStringWriter.Create;
  try
    jWriter:=TJsonTextWriter.Create(textWriter);
    try
      jWriter.WriteStartObject;
      jWriter.WritePropertyName('values');
      jWriter.WriteValue('wuppdi');
      jWriter.WriteEndObject;
      Result:=jWriter.Writer.ToString;
    finally
      jWriter.Free;
    end;
  finally
    textWriter.Free;
  end;
end;
oder alternativ auch so
Delphi-Quellcode:
function TmyClass.GetInfoAsJSON: string;
var
  jWriter: TJsonTextWriter;
  textWriter: TTextWriter;
begin
  jWriter := nil;
  textWriter := TStringWriter.Create;
  try
    jWriter:=TJsonTextWriter.Create(textWriter);
    jWriter.WriteStartObject;
    jWriter.WritePropertyName('values');
    jWriter.WriteValue('wuppdi');
    jWriter.WriteEndObject;
    Result:=jWriter.Writer.ToString;
  finally
    jWriter.Free;
    textWriter.Free;
  end;
end;
  Mit Zitat antworten Zitat
Bbommel

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

AW: Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

  Alt 20. Feb 2019, 09:17
Danke für die Rückmeldung, Schokohase. Das war das, was ich in meinem Beitrag mit "man kann sich den TextWriter auch beim Create merken" meinte - ist sicherlich die erstmal schönere Variante. Ich hatte halt jetzt schon soweit gebastelt, um dieses ganze Erzeugen und Freigaben nachher in Hilfsfunktionen (oder eine abgeleitete Klasse, mal sehen) auslagern zu können.

Aber meine eigentliche Frage hast du ja dann bestätigt: ja, es ist so, dass man immer beide Objekte braucht und tunlichst in der richtigen Reihenfolge freigeben muss.
  Mit Zitat antworten Zitat
Schokohase
(Gast)

n/a Beiträge
 
#4

AW: Erzeugen und Freigeben von TJSONTextWriter wirklich so umständlich?

  Alt 20. Feb 2019, 09:37
Ich würde den Code sogar noch etwas weiter aufdröseln zu
Delphi-Quellcode:
function TmyClass.GetInfoAsJSON: string;
var
  jWriter: TJsonTextWriter;
  textWriter: TTextWriter;
begin
  textWriter := TStringWriter.Create;
  try
    // start write json
    jWriter:=TJsonTextWriter.Create(textWriter);
    try
      jWriter.WriteStartObject;
      jWriter.WritePropertyName('values');
      jWriter.WriteValue('wuppdi');
      jWriter.WriteEndObject;
    finally
      jWriter.Free;
    end;
    // end write json
    Result := textWriter.ToString;
  finally
    textWriter.Free;
  end;
end;
und nun sieht man, dass man diesen JSON-Write Kram auch in eine eigene Methode auslagern kann.
Delphi-Quellcode:
procedure TmyClass.WriteJSONInfo(const AWriter: TTextWriter);
begin
  jWriter:=TJsonTextWriter.Create(AWriter);
  try
    jWriter.WriteStartObject;
    jWriter.WritePropertyName('values');
    jWriter.WriteValue('wuppdi');
    jWriter.WriteEndObject;
  finally
    jWriter.Free;
  end;
end;

function TmyClass.GetInfoAsJSON: string;
var
  textWriter: TTextWriter;
begin
  textWriter := TStringWriter.Create;
  try
    WriteJSONInfo(textWriter);
    Result := textWriter.ToString;
  finally
    textWriter.Free;
  end;
end;
und schon sieht das wesentlich entzerrter aus und man kann jetzt jeden beliebigen TextWriter von aussen übergeben (zum Testen, zum ...)
  Mit Zitat antworten Zitat
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 19:22 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