Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   REST.Json.TJson.ObjectToJsonString formatiert ausgeben? (https://www.delphipraxis.net/186350-rest-json-tjson-objecttojsonstring-formatiert-ausgeben.html)

TiGü 26. Aug 2015 10:53

Delphi-Version: XE7

REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Hallo zusammen,

zwecks diverser Konfigurationseinstellungen speichere ich mir Datentransferobjekte per REST.Json.TJson.ObjectToJsonString in einen String, der dann über eine TStringList auf der Festplatte landet

Wenn ich die entstandene Json-Datei per Editor, in diesen Fall Notepad++, öffne, dann steht der ganze JSON-String in einer Zeile.

Zwar kann man sich über die Notepad++-Erweiterung JSTool ganz leicht den JSON-String schön formatieren, aber kann ich nicht schon im Programmcode mit wenig Aufwand den JSON-String formatieren?
Gibt es da schon was fertiges im Emba-Framework?

Der schöne Günther 26. Aug 2015 11:01

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von TiGü (Beitrag 1313532)
Gibt es da schon was fertiges im Emba-Framework?

Nein, leider nicht.

Sir Rufo 26. Aug 2015 11:10

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Klar gibt es das:
Delphi-Quellcode:
function GetFormattedJson(AObject:TObject) : string
begin
  LJson := REST.Json.TJson.ObjectToJsonObject( AObject );
  try
    Result := REST.Json.TJson.Format( LJson );
  finally
    LJson.Free;
  end;
end;

TiGü 26. Aug 2015 11:38

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Wenn es Sir Rufo nicht geben würde, man müsste ihn glatt erfinden! :thumb:

Zwar ist das Ergebnis nicht ganz so hübsch, aber auf jeden Fall besser lesbarer und von Menschen bearbeitbarer (was für ein Wort!), als zuvor.

mkinzler 26. Aug 2015 11:44

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Wobei das eigentlich nicht der Sinn von json ist.

Der schöne Günther 26. Aug 2015 11:45

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Tja. Als ich das mal wollte, suchte ich auf StackOverflow nach "Delphi json prettyprint" und der dort allmächtige David Heffernan sagte "Nö, gibt's nicht".

Anstatt das kritisch zu hinterfragen legte ich die Hände in den Schoß und akzeptierte es. Was sagt das nur über mich aus? :oops:

TiGü 26. Aug 2015 11:55

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von mkinzler (Beitrag 1313539)
Wobei das eigentlich nicht der Sinn von json ist.

Ist ja auch erstmal nur für mich und allmal besser als INI- oder XML-Dateien.

TiGü 26. Aug 2015 11:57

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1313540)
Was sagt das nur über mich aus? :oops:

Das du zu faul warst, das Delphi-Forum deiner Wahl zu konsultieren? :o
Bzw. die Antworten auf SO über denen der DP stellt? :shock:

:wink:

Sir Rufo 26. Aug 2015 12:07

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1313540)
Anstatt das kritisch zu hinterfragen legte ich die Hände in den Schoß und akzeptierte es. Was sagt das nur über mich aus? :oops:

Typisches Weißkittel-Syndrom :mrgreen:

Ich bin so erzogen worden, dass Menschen mit einem weißen Kittel nur Menschen mit einem weißen Kittel sind. Und die haben die absolute Wahrheit und Weisheit genauso wenig gepachtet wie ich.

Es vereinfacht auch das Miteinander, wenn man jedem das Recht auf Unwissen und Irrtum belässt ;)

Uwe Raabe 26. Aug 2015 13:11

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1313540)
Tja. Als ich das mal wollte, suchte ich auf StackOverflow nach "Delphi json prettyprint" und der dort allmächtige David Heffernan sagte "Nö, gibt's nicht".

Wobei ich jetzt nicht sicher sagen kann, ob das damals schon drin war.

David's Präsenz dort ist schon manchmal unheimlich. Ich frage mich manchmal, was er sonst so überhaupt noch macht. Da er allerdings viele Dinge selbst implemenentiert, um von RTL und VCL unabhängig zu sein (weil das zumindest in der Vergangenheit nicht immer so funktionierte, wie er das wollte), sind seine Kenntnisse gerade in diesem Bereich nicht immer auf dem neuesten Stand.

Zugegeben, den vollen Leistungsumfang allein der RTL immer im Kopf parat zu haben, ist schon eine sportliche Herausforderung.

frankyboy1974 26. Aug 2015 13:16

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
hallo,

:kiss::balloon:

mfg

Sir Rufo 26. Aug 2015 13:39

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Also das ist dabei seit XE5
http://docwiki.embarcadero.com/Libra...n.TJson.Format
und XE5 wurde im September 2013 veröffentlicht.

Ja, zum Zeitpunkt der Antwort gab es das also schon.

Und um die Verwirrung auf SO in Grenzen zu halten, habe ich das mal als Kommentar an die Antwort gehängt ;)

Uwe Raabe 26. Aug 2015 14:06

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1313574)
Und um die Verwirrung auf SO in Grenzen zu halten, habe ich das mal als Kommentar an die Antwort gehängt ;)

:thumb:

TiGü 7. Dez 2015 11:00

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Falls jemand wieder vor einen ähnlichen Problem steht:
Ich habe eine noch schönere Lösung (für das Endergebnis) gefunden.
In der JsonWorkbench-Demo aus Delphi 10 Seattle (z.B. C:\Users\Public\Documents\Embarcadero\Studio\17.0\ Samples\Object Pascal\RTL\Json) gibt es Beautifier-Funktion.

Verkürzt sieht das so aus:

Delphi-Quellcode:
unit Format.JSON;

interface

uses
  System.SysUtils,
  System.Classes,
  System.Json.Writers,
  System.Json.Readers,
  System.Json.Types;

type
  TJsonStringWriter = class(TJsonTextWriter)
  private
    FStringBuilder: TStringBuilder;
    FStringWriter: TStringWriter;
  public
    constructor Create;
    destructor Destroy; override;
    function ToString: string; override;
  end;

  TJsonStringReader = class(TJsonTextReader)
  private
    FStringReader: TStringReader;
  public
    constructor Create(const AJson: string);
    destructor Destroy; override;
  end;

  function FormatJsonString(const AJson: string): string;

implementation

function FormatJsonString(const AJson: string): string;
var
  JsonWriter: TJsonStringWriter;
  JsonReader: TJsonStringReader;
begin
  JsonReader := TJsonStringReader.Create(AJson);
  try
    JsonWriter := TJsonStringWriter.Create;
    try
      JsonWriter.Formatting := TJsonFormatting.Indented;
      JsonWriter.WriteToken(JsonReader);
      Result := JsonWriter.ToString;
    finally
      JsonWriter.Free;
    end;
  finally
    JsonReader.Free;
  end;
end;

{ TJsonStringWriter }

constructor TJsonStringWriter.Create;
begin
  FStringBuilder := TStringBuilder.Create;
  FStringWriter := TStringWriter.Create(FStringBuilder);
  inherited Create(FStringWriter);
end;

destructor TJsonStringWriter.Destroy;
begin
  FStringWriter.Free;
  FStringBuilder.Free;
  inherited Destroy;
end;

function TJsonStringWriter.ToString: string;
begin
  Result := FStringBuilder.ToString;
end;

{ TJsonStringReader }

constructor TJsonStringReader.Create(const AJson: string);
begin
  FStringReader := TStringReader.Create(AJson);
  inherited Create(FStringReader);
end;

destructor TJsonStringReader.Destroy;
begin
  FStringReader.Free;
  inherited;
end;

end.

Sir Rufo 7. Dez 2015 12:48

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Ist das nicht ein wenig durch die Brust ins Auge?

Erst in einen JSON-String serialisieren
Dann den String parsen um den
Dann formatiert ausgeben lassen

:gruebel:

TiGü 7. Dez 2015 16:00

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Natürlich wäre es schon besser, wenn man der Funktion REST.Json.TJson.ObjectToJsonString mitgeben könnte, ob man den resultierenden JSONString "minified" oder "beautified" haben möchte.

Ich habe, angespornt durch dein kritische Frage, gerade anderthalb Stunden erfolglos versucht, das Result von TJSON.ObjectToJsonObject (ein TJSONObject = class sealed(TJSONValue)) sinnvoll zu einen formattierten JSON-String auszugeben.
Aber es will es mir nicht gelingen.
Vielleicht morgen mehr.

TiGü 7. Dez 2015 16:57

AW: REST.Json.TJson.ObjectToJsonString formatiert ausgeben?
 
Also ich habe einen möglichen Ansatz, aber an einer Stelle brauche ich die Länge für ein Byte-Array und mache hier wieder ein ToString.
Da muss ich noch nach Alternativen suchen.

Delphi-Quellcode:
unit Format.JSON;

interface

uses
  System.SysUtils,
  System.Classes,
  System.JSON,
  System.JSON.Writers,
  System.JSON.Readers,
  System.JSON.Types;

type
  TJsonStringWriter = class(TJsonTextWriter)
  private
    FStringBuilder: TStringBuilder;
    FStringWriter: TStringWriter;
  public
    constructor Create;
    destructor Destroy; override;
    function ToString: string; override;
  end;

  TJsonStreamReader = class(TJsonTextReader)
  private
    FStreamReader: TStreamReader;
  public
    constructor Create(const AJsonObject: TJSONObject);
    destructor Destroy; override;
  end;

function JsonObjectToFormattedString(const AJsonObject: TJSONObject): string;

implementation

function JsonObjectToFormattedString(const AJsonObject: TJSONObject): string;
var
  JsonWriter: TJsonStringWriter;
  JsonReader : TJsonStreamReader;
begin
  JsonReader := TJsonStreamReader.Create(AJsonObject);
  try
    JsonWriter := TJsonStringWriter.Create;
    try
      JsonWriter.Formatting := TJsonFormatting.Indented;
      JsonWriter.WriteToken(JsonReader);
      Result := JsonWriter.ToString;
    finally
      JsonWriter.Free;
    end;
  finally
    JsonReader.Free;
  end;
end;

{ TJsonStringWriter }

constructor TJsonStringWriter.Create;
begin
  FStringBuilder := TStringBuilder.Create;
  FStringWriter := TStringWriter.Create(FStringBuilder);
  inherited Create(FStringWriter);
end;

destructor TJsonStringWriter.Destroy;
begin
  inherited Destroy;
  FStringWriter.Free;
  FStringBuilder.Free;
end;

function TJsonStringWriter.ToString: string;
begin
  Result := FStringBuilder.ToString;
end;

{ TJsonStreamReader }

constructor TJsonStreamReader.Create(const AJsonObject: TJSONObject);
var
  LBytes : TBytes;
  LStream : TStream;
  Len : Integer;
begin
  Len := AJsonObject.ToString.Length * 6; // <--- das ist dann natürlich Quatsch, vielleicht kann man die benötigte Länge auch anderes bestimmen.
  SetLength(LBytes, Len);
  Len := AJsonObject.ToBytes(LBytes, 0);
  SetLength(LBytes, Len);
  LStream := TMemoryStream.Create;
  LStream.WriteBuffer(LBytes, Length(LBytes));
  Assert(LStream.Size <> 0);

  LStream.Position := 0;
  FStreamReader := TStreamReader.Create(LStream);
  inherited Create(FStreamReader);
end;

destructor TJsonStreamReader.Destroy;
begin
  inherited;
  FStreamReader.Free;
end;

end.


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