JSON in Swift kodieren und dekodieren
JSON-Daten
Das JSON-Format (JavaScript Object Notation) eignet sich aufgrund seiner einfach lesbaren Textform sehr gut für den Austausch strukturierter Daten. Dabei werden Daten über assoziative Arrays {...} und Listen [...] repräsentiert:
[
{
"name": "Bob",
"age": 32,
"phone": [
{ "type": "mobile", "number": "0123-456789" },
{ "type": "work", "number": "040-456789" }
]
},
{
"name": "Alice",
"age": 56,
"address": {
"street": "Musterstrasse 12",
"zip": "20095",
"city": "Hamburg"
}
}
]
JSON-Daten in Swift verarbeiten
Mit den Foundation-Klassen JSONDecoder und JSONEncoder können JSON-Daten in Swift geparst bzw. Swift-Werte als JSON ausgegeben werden. Dabei empfiehlt es sich, Datentypen als struct zu definieren, die 1:1 der JSON-Struktur entsprechen. Diese müssen konform zu dem Codable-Protokoll deklariert werden:
import Foundation
struct Person: Codable {
let name: String
let age: Int
let phone: [Phone]?
let address: Address?
}
struct Address: Codable {
let street, zip, city: String
}
struct Phone: Codable {
let type, number: String
}
Eine JSON-Datei, die im Xcode-Projekt enthalten ist und mit der App ausgeliefert wird, könnte folgendermaßen geparst werden:
if let jsonURL = Bundle.main.url(forResource: "persons", withExtension: "json") {
let jsonData = try Data(contentsOf: jsonURL)
let jsonDecoder = JSONDecoder()
let persons = try jsonDecoder.decode([Person].self, from: jsonData)
}
Ein Codable-Objekt kann folgendermaßen als JSON kodiert werden:
let jsonEncoder = JSONEncoder()
let jsonResultData = try jsonEncoder.encode(persons)
Namen der Eigenschaften anpassen, zusätzliche Eigenschaften
Mit einem CodingKeys-Enum können die Namen der Eigenschaften explizit festgelegt werden. Dazu ist es erforderlich, alle Eigenschaften aufzunehmen, die in der JSON-Ausgabe enthalten sein sollen. Eigenschaften die nicht in CodingKeys enthalten sind, werden ignoriert. So lassen sich Eigenschaften in einem Typ aufnehmen, die nicht mit kodiert werden sollen:
struct Person: Codable {
let name: String
let age: Int
var someOtherAttribute: String?
enum CodingKeys: String, CodingKey {
case name = "name"
case age = "ageYears"
}
}
Benennung von Eigenschaften: Snake-case vs. Camel-case
Eigenschaften in JSON-Daten folgen oft der Snake-case-Namenskonvention (z.B. phone_number). Den Swift-Namenskonventionen folgend würde eine entsprechende Eigenschaft nach Camel-case-Namenskonvention (z.B. phoneNumber) benannt werden. Praktischerweise kann eine entsprechende Konvertierung der Namenskonventionen konfiguriert werden:
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
jsonEncoder.keyEncodingStrategy = .convertToSnakeCase
Formatierte Ausgabe
Mit outputFormatting kann die Ausgabe der JSON-Serialisierung konfiguriert werden:
jsonEncoder.outputFormatting = .prettyPrinted
Datumswerten
Für die in JSON nicht-standardisierte Kodierung von Datumswerten kann eine entsprechende Option gesetzt werden:
jsonEncoder.dateEncodingStrategy = .iso8601
jsonDecoder.dateDecodingStrategy = .iso8601
Kodierungslogik anpassen
Wenn sich die Struktur des Swift-Typs von seiner kodierten Form unterscheidet, besteht die Möglichkeit, eine eigene Kodierungs- und Dekodierungslogik zu definieren:
Die Anpassung der Kodierungslogik ist nur bis zu einem gewissen Maß sinnvoll. Für sehr unregelmäßig strukturierte JSON-Datenformate könnte die Klasse JSONSerialization eine Alternative sein. Diese mappt nicht auf Swift-Typen, sondern liefert die Werte als Dictionary zurück. Eine weitere Möglichkeit, mit solchen Daten umzugehen ist die Verwendung des Open-Source-Frameworks SwiftyJSON, welches ein komfortables API für den dynamischen Zugriff auf JSON-Daten bereitstellt.
Tools
Codable-Typen generieren
Mit quicktype kann Swift-Code zur Typdefinition anhand von Beispiel-JSON-Daten generiert werden:
Dies kann auch per Kommandozeilentool erfolgen, zum Beispiel:
brew install quicktype quicktype https://www.ralfebert.de/examples/v3/countries.json --lang swift --no-initializers --no-coding-keys --density normal --acronym-style camel
JSON-Daten strukturiert anzeigen
Mit den Plug-ins JSONView für Chrome/Firefox oder SimplyJSON für Safari können JSON-Daten im Browser formatiert angezeigt werden:
Weiter geht's
→ Tutorial und Beispielprojekt: JSON-Daten mit URLSession laden und mit SwiftUI anzeigen