JSONSerialization — en inbyggd iOS-klass från Foundation-ramverket, avsedd för att konvertera JSON till Foundation-objekt och vice versa. Detta API är den grundläggande mekanismen för att arbeta med JSON på Apple-plattformar utan att ansluta tredjepartsbibliotek, och stöder tolkning av ordböcker, arrayer och primitiva typer. Enligt Apple Developer, 2024 stöder JSONSerialization arbete med Data, strömmar och läsmöjligheter för flexibel bearbetning av JSON-data.
Huvudpunkter
JSONSerialization — är en klass från Foundation-ramverket, tillgänglig på iOS, macOS, tvOS och watchOS. Den tillhandahåller metoder för att konvertera JSON Data till Foundation-objekt (NSDictionary, NSArray, NSString, NSNumber) och vice versa. Klassen dök upp i iOS 5 och fram till introduktionen av Codable (Swift 4) förblev den det huvudsakliga sättet att arbeta med JSON på Apple-plattformar. Trots sin ålder är JSONSerialization fortfarande efterfrågad i äldre projekt på Objective-C och i scenarier där dynamisk JSON-bearbetning krävs utan fast modellschema.
Trots tillkomsten av Codable förblir JSONSerialization relevant i flera scenarier. Dynamisk JSON-struktur — när svarsformatet ändras eller är okänt i förväg — kräver åtkomst till ordböcker via nycklar, vilket är enklare att göra via JSONSerialization. Klassen används också i Objective-C-projekt där Codable inte är tillgängligt, och vid arbete med strömmar för stegvis tolkning av stora JSON-filer. I tester och modeller gör isValidJSONObject och data(withJSONObject:options:) det möjligt att snabbt generera JSON-fixturer utan att ansluta tredjepartsbibliotek, vilket påskyndar utveckling och prototyping.
import Foundation
// Grundläggande struktur för användning av 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("JSON-tolkningsfel: \(error)")
}
JSONSerialization tillhandahåller fyra huvudmetoder för att arbeta med JSON. Huvudmetoden — jsonObject(with:options:), som konverterar Data till Foundation-objekt. Metoden data(withJSONObject:options:) utför omvänd serialisering. isValidJSONObject(_:) kontrollerar om ett objekt kan serialiseras. writeJSONObject(_:to:options:error:) skriver JSON direkt till en ström. För att läsa JSON från InputStream finns metoden jsonObject(with:options:), som accepterar en ström istället för Data, vilket är bekvämt vid integration med nätverksförfrågningar som returnerar strömmande data.
Metoden jsonObject tar emot Data och returnerar Any — vanligtvis NSDictionary eller NSArray. För säker arbete omvandlas resultatet till den förväntade typen genom villkorlig konvertering. Metoden data tar emot ett Foundation-objekt och returnerar Data med JSON-representation. Alternativet .prettyPrinted lägger till formatering med indrag för läsbarhet.
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)")
}
}
}
// Omvänd serialisering: 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)
}
Grundläggande tolkning av en ordbok med primitiva typer — den vanligaste operationen med JSONSerialization. Efter att ha mottagit Data via URLSession anropar utvecklaren jsonObject och konverterar resultatet till den förväntade typen. För arrayer av objekt används konvertering till [[String: Any]], varefter varje element bearbetas i en loop. Detta tillvägagångssätt är flexibelt men kräver manuell typHantering.
Verkliga API:er returnerar komplexa nästlade JSON-objekt med arrayer, datum och valfria fält. JSONSerialization bearbetar korrekt vilket nästlingsdjup som helst, men utvecklaren måste självständigt konvertera varje nivå till den erforderliga typen. För att förenkla denna uppgift rekommenderar Apple att använda Codable för typade data och JSONSerialization endast för dynamiska strukturer.
// Tolkning av svar från 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("Användare: \(name) (ID: \(userId))")
} catch let error as ParsingError {
print("Tolkning misslyckades: \(error)")
} catch {
print("Oväntat fel: \(error)")
}
}
enum ParsingError: Error {
case missingField
case invalidType
}
JSONSerialization kastar fel vid ogiltig JSON, typmissmatchning eller överskridande av nästlingsdjup. Felen tillhör typen CocoaError och innehåller en kod med beskrivning av problemet. Utvecklaren är skyldig att hantera dem genom do-catch-konstruktion, annars kommer applikationen att avslutas oväntat. De vanligaste felen: NSPropertyListReadCorruptError (felaktig JSON) och NSPropertyListReadUnknownError. Varje feltyp kräver sin egen hanteringsstrategi: vid ogiltigt format måste man begära återsändning av data, och vid strukturmissmatchning — uppdatera tolkningsmodellen.
Ogiltig JSON — den vanligaste orsaken till misslyckanden: ett saknat kommatecken, överflödigt tecken eller oescapade citattecken förstör hela tolkningen. Den andra typen av fel — missmatchning med förväntad struktur: till exempel returnerade servern en array istället för en ordbok. JSONSerialization.fragmentsAllowed tillåter läsning av JSON vars rot inte är en ordbok eller array, utan ett primitivt värde. Utvecklaren kan också stöta på felet med överskridande av nästlingsdjup när JSON innehåller för många hierarkinivåer.
JSONSerialization erbjuder flera alternativ för att konfigurera tolkning. .mutableContainers returnerar NSMutableDictionary och NSMutableArray istället för oföränderliga versioner, vilket är användbart vid modifiering av data efter tolkning. .mutableLeaves gör textvärden modifierbara. .fragmentsAllowed tillåter JSON vars rot inte är ett objekt eller array, utan en sträng eller siffra — bekvämt för enkla API-svar. Alternativen .withoutEscapingSlashes och .sortedKeys är tillgängliga för metoden data(withJSONObject:options:), och styr formateringen av serialiserad JSON. Alternativen skickas via en bitmask, vilket gör det möjligt att kombinera flera värden via operatorn | för flexibel konfiguration av tolkning.
// Hantering av olika feltryper
func safeParse(jsonData: Data) {
do {
let object = try JSONSerialization
.jsonObject(with: jsonData,
options: .fragmentsAllowed)
if let dictionary = object as? [String: Any] {
print("Ordbok med \(dictionary.count) nycklar")
} else if let array = object as? [Any] {
print("Array med \(array.count) objekt")
}
} catch CocoaError.propertyListReadCorrupt {
print("Korrupt JSON-data")
} catch let error as CocoaError {
print("Cocoa-fel: \(error)")
} catch {
print("Okänt fel: \(error)")
}
}
// Kontroll av objekts giltighet före serialisering
let testObject: [String: Any] = ["key": "value", "nested": ["a": 1]]
if JSONSerialization.isValidJSONObject(testObject) {
print("Giltigt JSON-objekt")
}
Prestandan för JSONSerialization påverkas av datastorlek och anropsfrekvens. Vid engångstolkning av ett litet serversvar är skillnaden omärkbar, men vid bearbetning av tiotals megabyte JSON eller frekventa anrop i loopar måste man beakta omkostnaderna för typkonvertering. JSONSerialization fungerar synkront i den aktuella tråden, därför rekommenderas för stora dokument att flytta tolkningen till en bakgrundskö via DispatchQueue.global(). Alternativt kan InputStream användas för strömbearbetning utan att ladda hela filen i minnet, vilket är kritiskt för applikationer med begränsade resurser. För att skriva JSON till en fil eller nätverksström gör metoden writeJSONObject(_:to:options:error:) det möjligt att dirigera serialiserad data direkt till OutputStream utan att skapa ett mellanliggande Data-objekt, vilket minskar minnesförbrukningen vid arbete med stora dokument.
Vanliga frågor
JSONSerialization — är en Foundation-klass för att konvertera JSON Data till Foundation-objekt (NSDictionary, NSArray) och vice versa. Den fungerar på iOS, macOS, tvOS och watchOS utan att ansluta ytterligare bibliotek.
Codable — är ett Swift-protokoll för automatisk typad serialisering som kompileras till typ säker kod. JSONSerialization arbetar med dynamiska Any-typer och kräver manuell konvertering. Codable är att föredra för nya projekt, JSONSerialization — för Objective-C och dynamisk data.
Använd do-catch-konstruktionen vid anrop av jsonObject. JSONSerialization-fel tillhör CocoaError. För felsökning, kontrollera NSPropertyListReadCorruptError som indikerar ogiltigt format på JSON-data.
Ja, JSONSerialization stöder vilket nästlingsdjup som helst för ordböcker och arrayer. Alla nästlade objekt konverteras till motsvarande Foundation-typer (NSDictionary, NSArray, NSString, NSNumber), med bibehållen ursprunglig JSON-struktur.
JSONSerialization är lämplig vid dynamisk JSON-struktur, i Objective-C-projekt, vid arbete med strömmar och för validering av JSON via isValidJSONObject. För typade strukturer med känt schema är Codable att föredra.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också