Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi deserialize JSON und TDateTime (https://www.delphipraxis.net/203844-delphi-deserialize-json-und-tdatetime.html)

Nebilim 31. Mär 2020 07:38

Delphi deserialize JSON und TDateTime
 
Hi liebe leute,

ich bekomme ein JSON über Rest von meinem Application Server. Generiert wird er über Jackson soweit ich weiß und sieht zum beispiel so aus:

Code:
{   "fertigbis":"19:00:00",
    "anzahl":1,
    "nummer":4711,
    "aenderung":"27.02.2020 15:31:47"
}
jetzt habe ich in Delphi ein Classe mit "f"-Properties. Diese ermöglichen ja eine direkte zuordnung der WertePaare über TJson.JsonToObject<TMyClass>(JSONString).

Jetzt mein Problem. Bei der automatischen zuordnung scheint wohl etwas schief zu laufen beim Datum. Denn da bekomme ich immer diese FehlerMeldung:

---------------------------
xxxx.Exe
---------------------------
'27.0.0 0:0:0,0' ist keine gültige Datums- und Uhrzeitangabe.
---------------------------
OK
---------------------------


Meine Frage: kann ich da eingreifen in die auto Zuordnung oder was muss ich anders machen damit es geht?

Uwe Raabe 31. Mär 2020 08:07

AW: Delphi deserialize JSON und TDateTime
 
Da kann man allerdings was machen, wenn man ein passendes JsonReflectAttribute und einen TJSONInterceptor dafür schreibt.
Delphi-Quellcode:
interface

uses
  REST.JsonReflect;

type
  JsonMyDateAttribute = class(JsonReflectAttribute)
  public
    constructor Create;
  end;

implementation

uses
  System.Rtti, System.SysUtils;

type
  TMyDateTimeInterceptor = class(TJSONInterceptor)
  protected
    procedure StringReverter(Data: TObject; Field, Arg: string); override;
  end;

procedure TMyDateTimeInterceptor.StringReverter(Data: TObject; Field, Arg: string);
var
  ctx: TRTTIContext;
  datetime: TDateTime;
begin
  datetime := StrToDateTime(Arg);
  ctx.GetType(Data.ClassType).GetField(Field).SetValue(Data, datetime);
end;

constructor JsonMyDateAttribute.Create;
begin
  inherited Create(ctObject, rtString, TMyDateTimeInterceptor);
end;
Unter der Annahme, daß deine Klasse in etwa so aussieht, musst du das entsprechende Feld mit dem Attribut dekorieren.
Delphi-Quellcode:
type
  TMyObject = class
  private
    FFertigbis: string;
    FAnzahl: Integer;
    FNummer: Integer;
    [JsonMyDate]
    FAenderung: TDateTime;
  public
    constructor Create;
  end;
Eine ganz ähnliche Technik wird auch in diesem Artikel beschrieben: Serializing Objects with TJson

Nebilim 31. Mär 2020 08:35

AW: Delphi deserialize JSON und TDateTime
 
Wow besten dank. Das ist ein ziemlich gutes Beispiel, dass man immer gut anwenden kann. Vielen dank.


ich bin mir sicher das es funktionieren wird, mein problem konnte ich allerdings so lösen das ich im Applicatin server das Datum formatiert habe
Code:
         DateFormat dateformatISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.GERMANY);
         mapper.setDateFormat(dateformatISO8601);
und dann beim Aufruf in Delphi ebenfalls die Option angegeben habe.

Delphi-Quellcode:
TJson.JsonToObject<TMyClass>(JSONString, [joDateFormatISO8601]);
Danke danke dein Beispiel wird aber sicherlich nochmal gute Dienste erweisen.

Uwe Raabe 31. Mär 2020 09:01

AW: Delphi deserialize JSON und TDateTime
 
OK, das ist natürlich der richtige Weg. Ich hatte mich eh schon gefragt, wer denn ein solches Datumsformat über JSON verschickt, aber wenn du das selbst unter Kontrolle hast, um so besser.

dummzeuch 31. Mär 2020 09:58

AW: Delphi deserialize JSON und TDateTime
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1460887)
Ich hatte mich eh schon gefragt, wer denn ein solches Datumsformat über JSON verschickt

Genau den Fall hatte ich auch gerade: Ein im Auftrag geschriebenes REST-Interface lieferte JSON mit Datumsangaben im deutschen Format. Ich wäre beinahe hintenüber gefallen, als sich das sah. Das gab erstmal virtuell ein paar auf die Finger für den, der das verbrochen hatte. Gerade für ein REST-Interface geht das gar nicht!

Aber da zeigt sich wieder, wie wenig Leute über Datumsformate nachdenken, wenn sie nicht schon davon gebissen wurden. Am schlimmsten sind dabei die Amis mit ihrem völlig hirnrissigen Format, das sie aber als ganz normal ansehen.

In einem anderen Auftrag gab es für Datums- und Zeitformat (und natürlich Dezimalpunkt vs. -komma) einen eigenen Abschnitt in der Spezifikation. Und das zu Recht!

himitsu 31. Mär 2020 10:08

AW: Delphi deserialize JSON und TDateTime
 
Ohne Anpassung kann man diesen Wert ja erstmal als String nehmen, anstatt als TDateTime, und dann manuell umwandeln.

Was hier aber als bescheidenes Ergebnis bleibt, dass wohl niemand "absichtlich" Deutsch schreibt, sondern dass es vermutlich nur die "aktuelle" Systemformatierung nutzt, welche sich auch ändern kann. (z.B. eine andere Systemsprache)
Deswegen gibt es für JSON ja extra ein "festes" Format, welches verwendet werden sollte.



Dezimalzahlen mit Komma statt Punkt, geht "eigentlich" nur als String,
denn ansonsten ist gleich der komplette JSON-Text geschrottet, da er von keinen normalen JSON-Parser interpretierrt werden kann.

Nebilim 1. Apr 2020 08:28

AW: Delphi deserialize JSON und TDateTime
 
Wie würde man denn am richtigsten ein Datum verschicken und dann in Delphi entgegen nehmen? so wie ich das gemacht habe oder noch anders?

Uwe Raabe 1. Apr 2020 08:40

AW: Delphi deserialize JSON und TDateTime
 
TJson.JsonToObject erlaubt diverse Datumsformate über einen optionalen Parameter zu verwenden. Ich würde mich an dem Default-Wert [joDateIsUTC, joDateFormatISO8601] orientieren.

himitsu 1. Apr 2020 11:10

AW: Delphi deserialize JSON und TDateTime
 
Per se ist in JSON ISO-8601 als UTC mit optionaler Zeitzone vorgegeben.
Hier hast Glück, dass diese Komponente auch andere Formate erlaubt.

DeddyH 1. Apr 2020 11:18

AW: Delphi deserialize JSON und TDateTime
 
In JSON ist überhaupt kein DateTime-Format vorgegeben. Es hat sich lediglich ISO8601 als Quasi-Standard etabliert, weil dieses Format am Besten geeignet ist und auch die Zeitzonen berücksichtigt.


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