Swifts JSONDecoder mit mehreren Datumsformaten in einer JSON-Zeichenkette?

9

Swift's JSONDecoder bietet eine dateDecodingStrategy Eigenschaft, die es uns erlaubt zu definieren, wie eingehende Datenfolgen in Übereinstimmung mit einem DateFormatter Objekt interpretiert werden.

Ich arbeite jedoch derzeit mit einer API, die abhängig von der Eigenschaft sowohl Datumstrings ( yyyy-MM-dd ) als auch datetime Strings ( yyyy-MM-dd HH:mm:ss ) zurückgibt. Gibt es eine Möglichkeit, die JSONDecoder dies zu behandeln, da das angegebene DateFormatter -Objekt nur mit einem einzigen dateFormat gleichzeitig umgehen kann?

Eine harmlose Lösung besteht darin, die begleitenden Decodable -Modelle so umzuschreiben, dass sie nur Zeichenfolgen als ihre Eigenschaften akzeptieren und öffentliche Date getter / setter-Variablen bereitstellen, aber das scheint mir eine schlechte Lösung zu sein. Irgendwelche Gedanken?

    
RamwiseMatt 21.06.2017, 17:30
quelle

4 Antworten

16

Es gibt einige Möglichkeiten, damit umzugehen:

  • Sie können eine DateFormatter -Unterklasse erstellen, die zuerst das Datum / Uhrzeit-Zeichenfolgenformat versucht. Wenn dies fehlschlägt, wird das einfache Datumsformat
  • versucht
  • Sie können eine .custom Date -Decodierungsstrategie angeben, in der Sie die Decoder für eine singleValueContainer() fragen, eine Zeichenkette dekodieren und sie durch die gewünschten Formatierungen übergeben, bevor Sie das analysierte Datum übergeben
  • Sie können einen Wrapper um den Date -Typ erstellen, der eine benutzerdefinierte init(from:) und encode(to:) bietet, was dies tut (aber das ist nicht wirklich besser als eine .custom Strategie)
  • Sie können einfache Zeichenfolgen verwenden, wie Sie
  • vorschlagen
  • Sie können eine benutzerdefinierte init(from:) für alle Typen bereitstellen, die diese Daten verwenden und verschiedene Dinge dort versuchen

Alles in allem werden die ersten beiden Methoden wahrscheinlich am einfachsten und saubersten sein - Sie werden die standardmäßige synthetisierte Implementierung von Codable überall beibehalten, ohne die Typsicherheit zu opfern.

    
Itai Ferber 21.06.2017, 21:51
quelle
15

Bitte versuchen Sie den Decoder wie folgt konfiguriert:

%Vor%     
Leszek Żarna 15.09.2017 20:11
quelle
4

Angesichts dieses gleichen Problems habe ich folgende Erweiterung geschrieben:

%Vor%

Diese Erweiterung ermöglicht es Ihnen, eine DateDecodingStrategy für den JSONDecoder zu erstellen, der mehrere unterschiedliche Datumsformate innerhalb derselben JSON-Zeichenfolge verarbeitet. Die Erweiterung enthält eine Funktion, die die Implementierung eines Abschlusses erfordert, der Ihnen einen CodingKey gibt, und es liegt an Ihnen, den richtigen DateFormatter für den bereitgestellten Schlüssel anzugeben.

Sagen wir, dass Sie folgendes JSON haben:

%Vor%

Das folgende Struct:

%Vor%

Um den JSON zu dekodieren, würden Sie den folgenden Code verwenden:

%Vor%     
S.Moore 10.11.2017 05:21
quelle
2

Es gibt keine Möglichkeit, dies mit einem einzelnen Encoder zu tun. Am besten passen Sie hier die Methoden encode(to encoder:) und init(from decoder:) an und stellen Sie eine eigene Übersetzung für diese Werte bereit, wobei die integrierte Datumsstrategie für die andere beibehalten wird.

Es könnte sich lohnen, zu diesem Zweck einen oder mehrere Formatierer in das Objekt userInfo zu übergeben.

    
Ben Scheirman 21.06.2017 18:15
quelle