Hier ist mein JSON
{
"id": 1,
"user": {
"user_name": "Tester",
"real_info": {
"full_name":"Jon Doe"
}
},
"reviews_count": [
{
"count": 4
}
]
}
Hier ist die Struktur, in der ich sie speichern möchte (unvollständig)
struct ServerResponse: Decodable {
var id: String
var username: String
var fullName: String
var reviewCount: Int
enum CodingKeys: String, CodingKey {
case id,
// How do i get nested values?
}
}
Ich habe mir Apples Dokumentation zum Dekodieren verschachtelter Strukturen angesehen, verstehe aber immer noch nicht, wie die verschiedenen Ebenen des JSON richtig ausgeführt werden. Jede Hilfe wird sehr geschätzt.
Encodable
dieServerResponse
Struktur nach dem gleichen Ansatz . Ist es überhaupt möglich?ServerResponse
hat weniger Daten alsRawServerResponse
. Sie können dieRawServerResponse
Instanz erfassen , mit Eigenschaften von aktualisierenServerResponse
und dann den JSON daraus generieren. Sie können bessere Hilfe erhalten, indem Sie eine neue Frage mit dem spezifischen Problem stellen, mit dem Sie konfrontiert sind.Um Ihr Problem zu lösen, können Sie Ihre
RawServerResponse
Implementierung in mehrere logische Teile aufteilen (mit Swift 5).# 1. Implementieren Sie die Eigenschaften und erforderlichen Codierungsschlüssel
# 2. Legen Sie die Dekodierungsstrategie für die
id
Eigenschaft fest#3. Legen Sie die Dekodierungsstrategie für die
userName
Eigenschaft fest# 4. Legen Sie die Dekodierungsstrategie für die
fullName
Eigenschaft fest# 5. Legen Sie die Dekodierungsstrategie für die
reviewCount
Eigenschaft festVollständige Implementierung
Verwendung
quelle
struct
Ihnenenum
mit Schlüsseln verwendet. das ist viel eleganter 👍Anstatt eine große
CodingKeys
Aufzählung mit allen Schlüsseln zu haben, die Sie zum Dekodieren des JSON benötigen, würde ich empfehlen, die Schlüssel für jedes Ihrer verschachtelten JSON-Objekte aufzuteilen und verschachtelte Aufzählungen zu verwenden, um die Hierarchie beizubehalten:Dies erleichtert das Verfolgen der Schlüssel auf jeder Ebene in Ihrem JSON.
Nun bedenken Sie Folgendes:
Ein Schlüsselcontainer wird zum Dekodieren eines JSON-Objekts verwendet und mit einem
CodingKey
konformen Typ (wie den oben definierten) dekodiert .Ein Container ohne Schlüssel wird zum Decodieren eines JSON-Arrays verwendet und nacheinander decodiert (dh jedes Mal, wenn Sie eine Decodierungs- oder verschachtelte Containermethode aufrufen, wird zum nächsten Element im Array übergegangen). Im zweiten Teil der Antwort erfahren Sie, wie Sie eine durchlaufen können.
Nachdem Sie Ihren Schlüsselcontainer der obersten Ebene mit
container(keyedBy:)
(da Sie ein JSON-Objekt auf der obersten Ebene haben) vom Decoder abgerufen haben, können Sie die folgenden Methoden wiederholt verwenden:nestedContainer(keyedBy:forKey:)
um ein verschachteltes Objekt von einem Objekt für einen bestimmten Schlüssel abzurufennestedUnkeyedContainer(forKey:)
um ein verschachteltes Array von einem Objekt für einen bestimmten Schlüssel abzurufennestedContainer(keyedBy:)
um das nächste verschachtelte Objekt aus einem Array abzurufennestedUnkeyedContainer()
um das nächste verschachtelte Array von einem Array zu erhaltenBeispielsweise:
Beispieldecodierung:
Durch einen nicht verschlüsselten Behälter iterieren
Betrachten Sie den Fall, wo Sie wollen
reviewCount
eine sein[Int]
, wobei jedes Element den Wert darstellt , für den"count"
Schlüssel in der verschachtelten JSON:Sie müssen den verschachtelten Container ohne Schlüssel durchlaufen, den verschachtelten Container mit Schlüssel bei jeder Iteration abrufen und den Wert für den
"count"
Schlüssel dekodieren . Du kannst den ... benutzencount
Eigenschaft des nicht verschlüsselten Containers verwenden, um das resultierende Array vorab zuzuweisen, und dann dasisAtEnd
Eigenschaft, um es zu durchlaufen.Beispielsweise:
quelle
I would advise splitting the keys for each of your nested JSON objects up into multiple nested enumerations, thereby making it easier to keep track of the keys at each level in your JSON
?CodingKeys
Aufzählung mit allen Schlüsseln zu haben, die Sie zum Dekodieren Ihres JSON-Objekts benötigen, sollten Sie sie für jedes JSON-Objekt in mehrere Aufzählungen aufteilen - zum Beispiel im obigen Code, den wirCodingKeys.User
mit den Schlüsseln haben um das Benutzer-JSON-Objekt ({ "user_name": "Tester", "real_info": { "full_name": "Jon Doe" } }
) zu dekodieren , also nur die Schlüssel für"user_name"
&"real_info"
.reviews_count
was ein Array von Wörterbuch ist. Derzeit funktioniert der Code wie erwartet. Mein reviewsCount hat immer nur einen Wert im Array. Aber was wäre, wenn ich tatsächlich ein Array von review_count wollte, dann müsste ich es einfachvar reviewCount: Int
als Array deklarieren, oder? ->var reviewCount: [Int]
. Und dann müsste ich auch dieReviewsCount
Aufzählung bearbeiten, oder?Int
, sondern ein Array von JSON-Objekten ist, die jeweils einenInt
Wert für einen bestimmten Schlüssel haben. Sie müssen also durchlaufen den nicht verschlüsselten Container und holen Sie sich alle verschachtelten Schlüsselcontainer, dekodieren Sie einenInt
für jeden (und hängen SieViele gute Antworten wurden bereits veröffentlicht, aber es gibt eine einfachere Methode, die IMO noch nicht beschrieben hat.
Wenn die JSON-Feldnamen mit geschrieben werden
snake_case_notation
, können Sie diecamelCaseNotation
in Ihrer Swift-Datei weiterhin verwenden.Sie müssen nur einstellen
Nach dieser Zeile Swift vergleicht Swift automatisch alle
snake_case
Felder aus dem JSON mit dencamelCase
Feldern im Swift-Modell.Z.B
Hier ist der vollständige Code
1. Schreiben des Modells
2. Einstellen des Decoders
3. Dekodierung
quelle
quelle
jsonStr
, können Sie diese anstelle der beidenguard let
oben genannten s verwenden:guard let jsonStrData: Data? = jsonStr.data(using: .utf8)! else { print("error") }
KonvertierenjsonStrData
Sie sie dann in Ihre Struktur, wie oben in derlet yourObject
Zeile beschriebenSie können auch die von mir vorbereitete Bibliothek KeyedCodable verwenden . Es wird weniger Code benötigt. Lassen Sie mich wissen, was Sie darüber denken.
quelle