Serializarea este procesul de transformare a unui obiect sau a unei structuri de date într-un format secvențial, potrivit pentru transmiterea prin rețea sau salvarea în fișier. Procesul invers, deserializarea, restaurează datele în starea inițială. Potrivit MDN Web Docs, serializarea este necesară pentru orice comunicare între procese. Serializarea stă la baza REST API, a memorării în cache și a schimbului de date între componentele aplicației.
Principalele puncte
Serializarea este procesul de transformare a unui obiect aflat în memoria operativă într-o secvență liniară de octeți sau caractere care poate fi transmisă prin rețea, salvată în fișier sau trimisă altui proces. Fără serializare, comunicarea în rețea, stocarea stării și comunicarea între procese nu sunt posibile.
Serializarea include două procese opuse. Procesul direct (serializarea) ambalează datele într-un format pentru transmitere. Procesul invers (deserializarea) restaurează datele înapoi într-un obiect. Deserializarea este critică pentru securitate: datele de intrare incorecte pot duce la vulnerabilități în aplicație.
În dezvoltarea aplicațiilor mobile, serializarea este utilizată peste tot: trimiterea cererilor la server și procesarea răspunsurilor, salvarea stării aplicației la rotirea ecranului, memorarea în cache a datelor pe disc și transmiterea datelor între ecrane prin Intent (Android) sau Segue (iOS).
Formatele de serializare se împart în text și binare. Formatele text (JSON, XML) sunt lizibile de către om și nu necesită instrumente pentru vizualizare. Formatele binare (Protobuf, FlatBuffers, MessagePack) sunt mai compacte și mai rapide, dar nu sunt lizibile fără deserializare. Alegerea formatului este un compromis între performanță și confortul depanării.
Pe lângă JSON, XML și Protobuf, există formate specializate: FlatBuffers de la Google pentru jocuri și AR, MessagePack — alternativă binară compactă a JSON, Avro de la Apache pentru date mari în Kafka, YAML — format de configurare cu suport pentru comentarii.
| Format | Tip | Schema | Dimensiune | Viteză |
|---|---|---|---|---|
| JSON | Text | Opțional | Medie | Medie |
| XML | Text | XSD | Mare | Mică |
| Protobuf | Binar | Obligatoriu | Mic | Ridicată |
| FlatBuffers | Binar | Obligatoriu | Mic | Maximă |
| MessagePack | Binar | Nu | Mic | Ridicată |
| Avro | Binar | JSON Schema | Mic | Ridicată |
Serializarea pe platformele mobile are specificul ei: trafic limitat, procesoare mai slabe și necesitatea salvării stării la rotirea ecranului. Pe Android se utilizează Gson, Moshi, Kotlinx Serialization. Pe iOS — Codable, JSONSerialization, PropertyListEncoder. Alegerea corectă a bibliotecii influențează critic performanța aplicației.
Kotlinx Serialization — bibliotecă modernă de la JetBrains pentru Kotlin Multiplatform Mobile. Suportă JSON, Protobuf, CBOR și formate personalizate. Generarea codului are loc în etapa de compilare prin pluginul Kotlin Serialization, ceea ce asigură performanță ridicată fără utilizarea reflexiei.
Biblioteca Kotlinx Serialization utilizează adnotarea @Serializable pentru clase și pluginul de compilator pentru generarea serializatoarelor. Aceasta asigură performanță ridicată și siguranța tipurilor. Formatul implicit este JSON, dar sunt suportate și alte formate prin module suplimentare.
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
@Serializable
data class Project(
val id: Int,
val name: String,
val platforms: List<String>,
val active: Boolean
)
val json = Json {
prettyPrint = true
ignoreUnknownKeys = true
encodeDefaults = true
}
fun main() {
val project = Project(1, "MobileApp",
listOf("Android", "iOS"), true)
// Serializare
val jsonString = json.encodeToString(project)
// Deserializare
val restored = json.decodeFromString<Project>(jsonString)
}
Protocolul Codable — mecanismul încorporat de serializare în Swift. Acesta combină protocoalele Encodable (serializare) și Decodable (deserializare). JSONEncoder și JSONDecoder procesează automat structuri imbricate, array-uri, valori opționale și chei personalizate prin CodingKeys.
import Foundation
struct AppConfig: Codable {
let appName: String
let version: String
let features: [String]
let isProduction: Bool
}
let config = AppConfig(
appName: "MyApp",
version: "2.1.0",
features: ["push", "analytics", "offline"],
isProduction: true
)
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
guard let data = try? encoder.encode(config) else { return }
let jsonString = String(data: data, encoding: .utf8)
Performanța formatelor de serializare se evaluează după trei metrici: dimensiunea mesajului, viteza de serializare și viteza de deserializare. Pentru aplicațiile mobile, toate trei sunt critice: dimensiunea influențează traficul și timpul de încărcare, viteza — receptivitatea interfeței și timpul de pornire al aplicației.
Protobuf și FlatBuffers arată cele mai bune rezultate datorită reprezentării binare. FlatBuffers se remarcă prin faptul că nu necesită o etapă separată de deserializare — datele se citesc direct din bufferul binar, ceea ce este ideal pentru jocuri și aplicații AR cu cerințe de latență minimă. JSON rămâne cel mai popular format pentru REST API, în ciuda performanței inferioare, datorită simplității și universalității.
| Scenariu | Format recomandat | Motiv |
|---|---|---|
| REST API | JSON | Universalitate, lizibilitate, suport |
| Microservicii | Protobuf | Compactitate, viteză, gRPC |
| Jocuri / AR | FlatBuffers | Zero-copy, latență minimă |
| Big Data | Avro | Compatibilitate cu Kafka și Hadoop |
| Configurare | YAML | Comentarii, lizibilitate |
| Android layouts | XML | Standard de platformă |
Testele practice pe un set de 1000 de obiecte utilizator arată: Protobuf creează mesaje de 12 KB (JSON — 85 KB, XML — 120 KB). Timpul de serializare: Protobuf — 2 ms, JSON — 8 ms, XML — 25 ms. Aceste cifre fac formatele binare preferate pentru sistemele cu încărcare mare și aplicații mobile cu trafic limitat.
Exemplele demonstrează serializarea aceluiași obiect în diferite formate. Acest lucru ajută la compararea vizuală a dimensiunii și lizibilității. Același obiect User va fi serializat în JSON, XML și Protobuf — se vede clar că JSON este mai compact decât XML, iar Protobuf este cel mai compact și în același timp ilizibil.
JSON — sintaxă minimalistă, chei în ghilimele, valori de diferite tipuri. Ocupă 80 de caractere. Lizibilitate ridicată, structură vizuală clară. Potrivit pentru API-uri unde viteza de dezvoltare și depanare este importantă.
XML — fiecare element este înfășurat într-un tag de deschidere și închidere. Ocupă 150 de caractere. Lizibilitate medie, structură strictă. Potrivit pentru fluxul de documente și sisteme care necesită validare prin XSD.
Protobuf — binar, 32 de octeți pentru aceste date. Ilizibil — necesită deserializare pentru vizualizare. Dimensiunea minimă îl face ideal pentru sisteme cu încărcare mare și aplicații mobile.
{
"id": 42,
"name": "IT Sectr",
"email": "team@itsectr.com",
"role": "admin",
"active": true
}
<user>
<id>42</id>
<name>IT Sectr</name>
<email>team@itsectr.com</email>
<role>admin</role>
<active>true</active>
</user>
Cele mai bune practici ajută la evitarea erorilor tipice și alegerea strategiei corecte de serializare pentru proiect. Respectarea acestor recomandări îmbunătățește performanța, securitatea și mentenanța codului.
Securitatea serializării — aspect critic, mai ales la deserializarea datelor din surse neverificate. Atacurile asupra deserializării pot duce la executarea de cod de la distanță (RCE), una dintre cele mai periculoase vulnerabilități în aplicațiile web și mobile. Cele mai cunoscute cazuri sunt legate de Java Serializable și Python pickle.
Protobuf și JSON au protecție încorporată împotriva unor astfel de atacuri, deoarece lucrează doar cu date, nu cu obiecte arbitrare. Java Serializable, dimpotrivă, poate restaura orice clase disponibile în classpath, ceea ce îl face periculos pentru primirea datelor din surse externe. Pe Android se recomandă utilizarea Kotlinx Serialization sau Moshi în locul Java Serialization standard.
Măsuri suplimentare de securitate: stabiliți o limită pentru dimensiunea datelor de intrare, validați schema înainte de deserializare, nu aveți încredere în Content-Type din antetele HTTP, utilizați o listă albă (allowlist) pentru clasele permise. Actualizați regulat bibliotecile de serializare, deoarece vulnerabilitățile în ele sunt descoperite și remediate periodic.
Întrebări frecvente
Serializarea transformă obiectul într-o secvență de octeți, marshalling transmite datele între spații de adrese diferite cu păstrarea tipurilor și structurii. Marshalling include serializarea ca parte a procesului, dar poate include și codificarea referințelor și gestionarea memoriei.
FlatBuffers de la Google asigură viteza maximă datorită deserializării zero-copy — datele se citesc direct din bufferul binar fără transformare. Protobuf ocupă locul doi, JSON — locul trei. XML este cel mai lent format dintre cele răspândite.
Kotlinx Serialization — cea mai bună alegere pentru proiecte noi în Kotlin: generare la compilare, suport Kotlin Multiplatform, null safety. Moshi — alegere bună pentru proiecte în Java, mai performant decât Gson. Gson — cea mai simplă bibliotecă pentru început, dar mai lentă și utilizează reflexia.
Referințele ciclice duc la recursivitate infinită la serializare. Soluții: utilizați referințe ID în loc de referințe directe la obiecte, aplicați adaptoare speciale de serializare (de exemplu, @JsonIgnore în Jackson) sau reproiectați modelul de date pentru a elimina ciclurile.
Da, mai ales deserializarea datelor din surse nesigure. Vulnerabilitățile de deserializare pot duce la executarea de cod de la distanță. Recomandări: nu deserializați date din surse neverificate, utilizați liste albe de clase la deserializare și validați schema datelor înainte de procesare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și