JSONSerialization — vestavěná třída iOS z frameworku Foundation, určená pro převod JSON na objekty Foundation a zpět. Toto API je základním mechanismem práce s JSON na platformách Apple bez připojování knihoven třetích stran, podporující parsování slovníků, polí a primitivních typů. Podle Apple Developer, 2024 JSONSerialization podporuje práci s Data, streamy a možnostmi čtení pro flexibilní zpracování JSON dat.
Hlavní body
JSONSerialization — je třída z frameworku Foundation, dostupná na iOS, macOS, tvOS a watchOS. Poskytuje metody pro převod JSON Data na objekty Foundation (NSDictionary, NSArray, NSString, NSNumber) a zpět. Třída se objevila v iOS 5 a až do zavedení Codable (Swift 4) zůstala hlavním způsobem práce s JSON na platformách Apple. Navzdory stáří zůstává JSONSerialization žádaný v legacy projektech na Objective-C a ve scénářích, kde je vyžadováno dynamické zpracování JSON bez pevného schématu modelu.
Navzdory příchodu Codable zůstává JSONSerialization relevantní v několika scénářích. Dynamická struktura JSON — když se formát odpovědi mění nebo je předem neznámý — vyžaduje přístup ke slovníkům pomocí klíčů, což je jednodušší provést přes JSONSerialization. Třída se také používá v projektech Objective-C, kde Codable není k dispozici, a při práci s streamy pro fázové parsování velkých JSON souborů. V testech a maketách umožňují isValidJSONObject a data(withJSONObject:options:) rychlé generování JSON fixtur bez připojování knihoven třetích stran, což urychluje vývoj a prototypování.
import Foundation
// Základní struktura použití JSONSerialization
let jsonString = """
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
"""
guard let jsonData = jsonString.data(using: .utf8) else {
return
}
do {
let json = try JSONSerialization
.jsonObject(with: jsonData,
options: .mutableContainers)
print(json)
} catch {
print("Chyba parsování JSON: \(error)")
}
JSONSerialization poskytuje čtyři hlavní metody pro práci s JSON. Hlavní metoda — jsonObject(with:options:), která převádí Data na objekty Foundation. Metoda data(withJSONObject:options:) provádí reverzní serializaci. isValidJSONObject(_:) kontroluje, zda lze objekt serializovat. writeJSONObject(_:to:options:error:) zapisuje JSON přímo do streamu. Pro čtení JSON z InputStream existuje metoda jsonObject(with:options:), která přijímá stream místo Data, což je výhodné při integraci s síťovými požadavky vracejícími streamovaná data.
Metoda jsonObject přijímá Data a vrací Any — obvykle NSDictionary nebo NSArray. Pro bezpečnou práci je výsledek převeden na očekávaný typ pomocí podmíněné konverze. Metoda data přijímá objekt Foundation a vrací Data s JSON reprezentací. Volba .prettyPrinted přidává formátování s odsazením pro čitelnost.
let jsonString = """
{
"products": [
{"id": 1, "name": "iPhone", "price": 999},
{"id": 2, "name": "iPad", "price": 799}
]
}
"""
let data = Data(jsonString.utf8)
if let json = try? JSONSerialization
.jsonObject(with: data) as? [String: Any],
let products = json["products"] as? [[String: Any]] {
for product in products {
if let name = product["name"] as? String {
print("Produkt: \(name)")
}
}
}
// Reverzní serializace: objekt -> JSON
let outputDict: [String: Any] = ["status": "ok", "count": 42]
if let outputData = try? JSONSerialization
.data(withJSONObject: outputDict,
options: .prettyPrinted) {
String(data: outputData, encoding: .utf8)
}
Základní parsování slovníku s primitivními typy — nejčastější operace s JSONSerialization. Po obdržení Data přes URLSession vývojář zavolá jsonObject a převede výsledek na očekávaný typ. Pro pole objektů se používá převod na [[String: Any]], poté je každý prvek zpracován ve smyčce. Tento přístup je flexibilní, ale vyžaduje ruční správu typů.
Skutečná API vracejí složité vnořené JSON objekty s poli, daty a volitelnými poli. JSONSerialization správně zpracovává jakoukoli hloubku vnoření, ale vývojář musí každou úroveň nezávisle převést na požadovaný typ. Pro zjednodušení tohoto úkolu Apple doporučuje používat Codable pro typová data a JSONSerialization pouze pro dynamické struktury.
// Parsování odpovědi z API
func parseUserResponse(data: Data) {
do {
guard let json = try JSONSerialization
.jsonObject(with: data) as? [String: Any]
else { return }
guard let userId = json["id"] as? Int,
let name = json["name"] as? String
else {
throw ParsingError.missingField
}
print("Uživatel: \(name) (ID: \(userId))")
} catch let error as ParsingError {
print("Parsování selhalo: \(error)")
} catch {
print("Neočekávaná chyba: \(error)")
}
}
enum ParsingError: Error {
case missingField
case invalidType
}
JSONSerialization vyhazuje chyby při neplatném JSON, nesouladu typů nebo překročení hloubky vnoření. Chyby patří do typu CocoaError a obsahují kód s popisem problému. Vývojář je povinen je zpracovávat pomocí konstrukce do-catch, jinak aplikace havaruje. Nejčastější chyby: NSPropertyListReadCorruptError (nesprávný JSON) a NSPropertyListReadUnknownError. Každý typ chyby vyžaduje vlastní strategii zpracování: při neplatném formátu je třeba požádat o opětovné odeslání dat, při nesouladu struktury — aktualizovat model parsování.
Neplatný JSON — nejčastější příčina selhání: chybějící čárka, přebytečný znak nebo neescapovaný uvozovka rozbije celé parsování. Druhý typ chyb — nesoulad s očekávanou strukturou: například server vrátil pole místo slovníku. JSONSerialization.fragmentsAllowed umožňuje číst JSON, jehož kořenem není slovník nebo pole, ale primitivní hodnota. Vývojář se také může setkat s chybou překročení hloubky vnoření, když JSON obsahuje příliš mnoho úrovní hierarchie.
JSONSerialization poskytuje několik možností pro konfiguraci parsování. .mutableContainers vrací NSMutableDictionary a NSMutableArray místo neměnných verzí, což je užitečné při úpravě dat po parsování. .mutableLeaves činí textové hodnoty měnitelnými. .fragmentsAllowed povoluje JSON, jehož kořenem není objekt nebo pole, ale řetězec nebo číslo — výhodné pro jednoduché API odpovědi. Volby .withoutEscapingSlashes a .sortedKeys jsou k dispozici pro metodu data(withJSONObject:options:), řídí formátování serializovaného JSON. Volby se předávají bitovou maskou, což umožňuje kombinovat více hodnot pomocí operátoru | pro flexibilní konfiguraci parsování.
// Zpracování různých typů chyb
func safeParse(jsonData: Data) {
do {
let object = try JSONSerialization
.jsonObject(with: jsonData,
options: .fragmentsAllowed)
if let dictionary = object as? [String: Any] {
print("Slovník s \(dictionary.count) klíči")
} else if let array = object as? [Any] {
print("Pole s \(array.count) položkami")
}
} catch CocoaError.propertyListReadCorrupt {
print("Poškozená JSON data")
} catch let error as CocoaError {
print("Cocoa chyba: \(error)")
} catch {
print("Neznámá chyba: \(error)")
}
}
// Kontrola platnosti objektu před serializací
let testObject: [String: Any] = ["key": "value", "nested": ["a": 1]]
if JSONSerialization.isValidJSONObject(testObject) {
print("Platný JSON objekt")
}
Na výkon JSONSerialization má vliv velikost dat a frekvence volání. Při jednorázovém parsování malé odpovědi serveru je rozdíl nepatrný, ale při zpracování desítek megabajtů JSON nebo častých voláních ve smyčkách je třeba zohlednit režii převodu typů. JSONSerialization pracuje synchronně v aktuálním vlákně, proto se u velkých dokumentů doporučuje přesunout parsování do fronty na pozadí pomocí DispatchQueue.global(). Alternativně lze použít InputStream pro streamové zpracování bez načítání celého souboru do paměti, což je kritické pro aplikace s omezenými zdroji. Pro zápis JSON do souboru nebo síťového streamu umožňuje metoda writeJSONObject(_:to:options:error:) přímé směrování serializovaných dat do OutputStream bez vytváření zprostředkujícího objektu Data, což snižuje spotřebu paměti při práci s velkými dokumenty.
Často kladené otázky
JSONSerialization — je třída Foundation pro převod JSON Data na objekty Foundation (NSDictionary, NSArray) a zpět. Pracuje na iOS, macOS, tvOS a watchOS bez připojování dalších knihoven.
Codable — je Swift protokol pro automatickou typovou serializaci, který se kompiluje do typově bezpečného kódu. JSONSerialization pracuje s dynamickými typy Any a vyžaduje ruční převod. Codable je preferován pro nové projekty, JSONSerialization — pro Objective-C a dynamická data.
Použijte konstrukci do-catch při volání jsonObject. Chyby JSONSerialization patří do CocoaError. Pro ladění zkontrolujte NSPropertyListReadCorruptError, který indikuje neplatný formát JSON dat.
Ano, JSONSerialization podporuje jakoukoli hloubku vnoření slovníků a polí. Všechny vnořené objekty jsou převedeny na odpovídající Foundation typy (NSDictionary, NSArray, NSString, NSNumber), přičemž je zachována původní JSON struktura.
JSONSerialization je vhodný při dynamické struktuře JSON, v Objective-C projektech, při práci s streamy a pro ověření platnosti JSON přes isValidJSONObject. Pro typové struktury se známým schématem je preferován Codable.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také