Deserializace je proces obnovy objektu z datového proudu JSON, XML nebo Protobuf, nezbytný pro každou mobilní aplikaci komunikující se vzdáleným API. Podle Apple Developer (2026) zůstává nesprávné zpracování příchozích dat jedním z častých důvodů pádů na zařízeních. JSONDecoder na iOS a Gson na Androidu jsou standardní nástroje, ale každý má své vlastnosti a omezení.
Hlavní body
Deserializace — proces převodu proudu bajtů nebo strukturovaného textu na objekt programovacího jazyka. V mobilním vývoji k tomuto procesu dochází pokaždé, když aplikace obdrží odpověď ze serveru: JSON řetězec se změní na instanci třídy User, Order nebo Product. Stabilita obrazovek zobrazujících data uživateli přímo závisí na správnosti deserializace.
Serializace a deserializace jsou vzájemně opačné procesy, v praxi zřídka symetrické. Serializace převádí objekt na řetězec pro odeslání na server, deserializace obnovuje objekt z přijatého řetězce. Server může odeslat pole, které v modelu klienta neexistuje, použít jiný formát data nebo vrátit null místo čísla. Podle Square Engineering (2025) je asymetrie formátů příčinou 23% chyb síťové vrstvy v Android aplikacích. Pro snížení rizika se používá verzování schématu a striktní kontraktová specifikace přes OpenAPI.
JSON zůstává nejoblíbenějším formátem pro mobilní API díky čitelnosti a vestavěné podpoře. Protobuf od Google se používá v high-load systémech — je 3-6krát kompaktnější než JSON a rychleji se parsuje, ale vyžaduje generování kódu z .proto souborů a je bez nástrojů nečitelný. XML se v moderních mobilních aplikacích vyskytuje méně často, ale používá se v SOAP službách podnikových systémů a konfiguračních souborech Android. MessagePack — binární formát podobný JSON strukturou, ale kompaktnější, oblíbený v systémech reálného času.
Proces deserializace prochází třemi fázemi. Nejprve tokenizace rozděluje surový text na lexémy: klíče, řetězce, čísla a oddělovače. Poté syntaktická analýza kontroluje správnost struktury — zda jsou závorky uzavřeny, zda je typ uvozovek správný, zda formát odpovídá specifikaci RFC 8259. Konečnou fází je mapování na objektový model aplikace, kde je každému JSON klíči přiřazena vlastnost třídy s ohledem na strategii pojmenování.
V mobilním vývoji se vytvořily dva přístupy k mapování. Reflection (Gson, JSONSerialization) analyzuje strukturu třídy za běhu přes Java Reflection API nebo Objective-C runtime — je flexibilní a nevyžaduje další konfiguraci, ale je pomalejší a spotřebovává více paměti. Code generation (Moshi codegen, kotlinx.serialization, Codable) generuje kód ve fázi kompilace: rychlejší, bezpečnější z hlediska typů a neodhaluje vnitřní strukturu přes reflection. JetBrains a Square doporučují code generation pro produkční sestavení — nárůst výkonu dosahuje 2-4krát v benchmarkách Google.
struct User: Codable {
let id: Int
let name: String
let email: String
let createdAt: Date
}
let json = """
{
"id": 42,
"name": "Alice",
"email": "alice@example.com",
"created_at": "2026-06-01T12:00:00Z"
}
"""
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let user = try decoder.decode(User.self, from: data)
Příklad deserializace JSON do modelu User ve Swiftu. Strategie convertFromSnakeCase automaticky převádí snake_case klíče API na camelCase vlastnosti modelu — standardní praxe v iOS projektech. Parametr data jsou surové bajty odpovědi serveru získané přes URLSession. Zpracování chyb přes try umožňuje zachytit neplatný JSON bez pádu aplikace.
JSONDecoder podporuje čtyři strategie klíčů: useDefaultKeys (přesná shoda), convertFromSnakeCase (snake_case → camelCase), custom (closure) a convertFromKebabCase (kebab-case → camelCase). Pro data jsou k dispozici .iso8601, .secondsSince1970, .millisecondsSince1970 a vlastní dateFormatter. Výběr správné strategie je prvním krokem ke stabilní deserializaci, který zabraňuje většině chyb neshody formátů.
JSONDecoder — standardní mechanismus deserializace v iOS SDK pracující s protokolem Codable. JSONDecoder automaticky parsuje JSON do instancí struct nebo class, podporuje vnořené objekty, pole a primitivní typy. Pro vlastní logiku se používá metoda init(from: Decoder) — umožňuje zpracovat nestandardní formáty, chybějící pole ve starší verzi API nebo sloučit několik JSON klíčů do jedné vlastnosti.
struct Order: Decodable {
let orderId: String
let amount: Double
let status: OrderStatus
enum OrderStatus: String, Decodable {
case pending, confirmed, shipped, cancelled
}
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let order = try decoder.decode(Order.self, from: jsonData)
DateDecodingStrategy určuje, jak JSONDecoder interpretuje řetězce s daty. Nejčastěji se používá .iso8601 — standardní formát REST API. Vnořený enum OrderStatus se automaticky dekóduje z hodnot JSON řetězců. To umožňuje vyhnout se magickým číslům a činí kód samodokumentujícím — stav objednávky má vždy přesně definovanou sadu hodnot.
Od Swift 4.2 Codable podporuje property wrappers pro vlastní deserializaci jednotlivých vlastností. @DefaultValue — oblíbený wrapper nastavující výchozí hodnotu, pokud pole v JSON chybí. @LosslessString převádí řetězec na číslo a naopak. To je užitečné zejména když server posílá id jako řetězec „123” a model očekává Int. Property wrappers redukují šablonový kód v init(from:) a činí modely čistšími.
Na Androidu výběr knihovny pro deserializaci závisí na jazyku a požadavcích projektu. Gson od Google — nejrozšířenější možnost pracující přes reflection, ale má problémy s výkonem na složitých hierarchiích. Moshi od Square podporuje jak reflection, tak code generation, spotřebovává méně paměti a rychleji zpracovává velké odpovědi. kotlinx.serialization od JetBrains — nativní Kotlin řešení s integrací do kompilátoru, které nepoužívá reflection vůbec.
@Serializable
data class User(
@SerialName("user_id")
val userId: Int,
val name: String,
val email: String,
@SerialName("created_at")
val createdAt: String
)
val json = Json { ignoreUnknownKeys = true }
val user = json.decodeFromString<User>(response)
@Serializable — anotace Kotlin kompilátoru aktivující generování kódu pro třídu. Parametr ignoreUnknownKeys zabraňuje pádu, pokud server odeslal pole, které v modelu neexistuje. Pro mapování snake_case klíčů se používá @SerialName — ekvivalent convertFromSnakeCase z iOS. Podle JetBrains (2026) knihovna podporuje multiplatformnost: stejná třída Serializable funguje na Androidu, iOS (KMP) a serverovém Kotlin.
Volba mezi knihovnami spočívá v kompromisu rychlost-flexibilita. Gson je dobrý pro prototypy a projekty v Javě — nevyžaduje anotace a funguje „z krabice”. Moshi zaujímá střední pozici: codegen přes @JsonClass(generateAdapter = true) poskytuje rychlost blízkou kotlinx.serialization a reflection režim flexibilitu Gson. kotlinx.serialization — nejrychlejší volba pro čisté Kotlin projekty, ale vyžaduje Kotlin 1.4+ a plugin Kotlin Serialization v Gradle.
| Knihovna | Mechanismus | Rychlost | KMP |
|---|---|---|---|
| Gson | Reflection | Nízká | Ne |
| Moshi | Reflection / Codegen | Střední / Vysoká | Ne |
| kotlinx.serialization | Compiler codegen | Vysoká | Ano |
Type mismatch — situace, kdy JSON obsahuje hodnotu jednoho typu a model očekává jiný. Server odeslal řetězec „42” místo čísla nebo číslo 1 místo boolean true. Na iOS JSONDecoder standardně vyvolá DecodingError.typeMismatch, na Androidu Gson se pokusí převést, Moshi a kotlinx.serialization vyžadují explicitní adaptéry. Řešení — používejte lenient strategie nebo vlastní deserializátory pro konkrétní pole.
Když server nezahrne volitelné pole, kód spadne s chybou. Optional ve Swiftu a nullable typy v Kotlin řeší problém: pokud je pole null nebo v JSON chybí, vlastnost získá hodnotu nil/null a aplikace pokračuje v činnosti. Pro povinná pole se vyplatí kontrolovat jejich přítomnost na úrovni API klienta před deserializací. Moshi a kotlinx.serialization standardně vyžadují všechna pole — nullable označení a výchozí hodnoty toto omezení odstraňují.
Změna JSON struktury na serveru — častý zdroj produkčních pádů. Standardní praxí je verzování schématu přes pole version v kořenovém objektu a podpora 2-3 předchozích verzí na klientovi. kotlinx.serialization umožňuje deklarovat několik modelů pro různé verze a vybrat správný podle pole version po prvotním parsování do JsonElement. Dodatečná ochrana — ignoreUnknownKeys pro nová pole a výchozí hodnoty pro pole, která mohou být odstraněna.
| Chyba | Příznak | Knihovna s ochranou |
|---|---|---|
| Type mismatch | DecodingError / výjimka | kotlinx — coerceInputValues = true |
| Chybějící pole | Pád při přístupu | Moshi — @Transient + default |
| Nesprávný formát data | Chyba dekódování | JSONDecoder — dateDecodingStrategy |
| Další pole | Ignorována nebo pád | kotlinx — ignoreUnknownKeys = true |
| Null v non-null poli | Pád za běhu | Moshi — lenient s @Nullable |
Logování chyb deserializace — povinná praxe v produkci. Obalte decode do do/catch, logujte raw JSON a typ očekávaného modelu do Crashlytics nebo Sentry. To umožní rychle určit, které pole kterého API se rozbilo a na které verzi aplikace. Bez logování vypadá chyba deserializace jako záhadný pád bez kontextu.
Často kladené otázky
Parsování — rozbor strukturovaného textu na jednotlivé prvky bez povinného vytváření typovaného modelu. Deserializace je zvláštní případ parsování, jehož výsledkem je plnohodnotný objekt jazyka se známými typy vlastností. Parsování může být proudové, deserializace vždy vytváří kompletní objekt.
Pro projekt v čistém Kotlin se doporučuje kotlinx.serialization — je integrována do kompilátoru, nepoužívá reflection a podporuje Kotlin Multiplatform. Pro existující projekt v Javě — Moshi s code generation. Gson je lépe ponechat pro legacy projekty, kde by jeho výměna vyžadovala značné úsilí.
Na iOS použijte keyDecodingStrategy = .convertFromSnakeCase v JSONDecoder. Na Androidu v kotlinx.serialization použijte @SerialName pro každé pole. V Moshi aplikujte @Json(name="field_name") nebo globální JsonAdapter.Factory. Jednotný styl na úrovni projektu je best practice dohodnutý v kontraktu API.
Nejčastější příčinou je neočekávané null od serveru pro pole deklarované jako povinné. Ve vývoji server vrací plná data, v produkci — zkrácenou odpověď. Řešení: označte všechna potenciálně chybějící pole jako nullable (Kotlin) nebo optional (Swift), používejte ignoreUnknownKeys a výchozí hodnoty.
Code generation (Moshi codegen, kotlinx.serialization, Codable) pracuje 2-4krát rychleji než reflection v benchmarkách Google. Kromě rychlosti je generování kódu bezpečnější z hlediska typů, nevyžaduje metadata tříd za běhu a typové chyby jsou odhaleny ve fázi kompilace, nikoli při deserializaci.
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é