Parsing — proces syntaktycznej analizy strukturyzowanych danych, wydobywający informacje z JSON, XML, CSV lub Protobuf do wykorzystania w aplikacji. Według danych Square Engineering (2025), wybór strategii parsingu bezpośrednio wpływa na wydajność aplikacji mobilnej. Parsing strumieniowy pozwala przetwarzać megabajty danych bez ładowania całego dokumentu do pamięci.
Najważniejsze
Parsing (analiza syntaktyczna) — proces przekształcania sekwencji znaków w strukturyzowaną reprezentację nadającą się do programowego przetwarzania. W kontekście programowania mobilnego pod parsingiem rozumie się analizę odpowiedzi serwera, plików konfiguracyjnych, lokalnego cache i plików zasobów. Każdy format wymaga własnego podejścia: JSON — lekki i wbudowany w SDK, XML — ścisły z walidacją schematu XSD, CSV — minimalistyczny dla danych tabelarycznych, Protobuf — binarny ze sztywnym schematem.
Każdy parser, niezależnie od formatu, przechodzi trzy etapy. Analiza leksykalna dzieli surowy tekst na tokeny: klucze, ciągi znaków, liczby, separatory i komentarze. Analiza składniowa sprawdza poprawność gramatyki — balans nawiasów w JSON, poprawność zagnieżdżenia tagów w XML. Budowanie struktury wyjściowej tworzy reprezentację obiektową: JSONObject, Map lub strumień tokenów do dalszego przetwarzania. Według danych Apple (2026), wbudowany parser Foundation na iOS używa leniwej analizy — waliduje tylko początek JSON, oszczędzając zasoby.
Ręczny parsing (JSONSerialization, XmlPullParser) daje pełną kontrolę nad procesem i jest przydatny przy niestandardowych formatach lub konieczności niestandardowej walidacji każdego pola. Automatyczne biblioteki (JSONDecoder, Moshi, kotlinx.serialization) przyspieszają rozwój, ale ukrywają szczegóły obsługi błędów. Wybór zależy od wymagań: jeśli struktura danych jest dynamiczna lub z góry nieznana — ręczny parsing jest preferowany. Jeśli schemat jest stały — automatyczna deserializacja skraca kod o 60–70%.
Parsing — szersza operacja: może być wykonywany strumieniowo i niekoniecznie tworzy typizowany obiekt. Deserializacja — szczególny przypadek parsingu, którego wynikiem zawsze jest instancja z góry znanej klasy z konkretnymi typami właściwości. Parser JSON rozbierze dokument na Map lub JsonElement, a deserializator przekształci ten sam JSON w konkretny obiekt User, Order lub Product ze znanymi polami i ich typami.
| Cecha | Parsing | Deserializacja |
|---|---|---|
| Wynik | JsonElement, Map, strumień tokenów | Typizowany obiekt (User, Order) |
| Tryb strumieniowy | Tak (SAX, JsonReader) | Nie (cały obiekt do pamięci) |
| Typizacja | Opcjonalna, dynamiczne typy | Obowiązkowa, statyczne typy |
| Przykład | XmlPullParser.next(), SAX events | json.decodeFromString<User>() |
Parsing strumieniowy — główna przewaga parsingu nad deserializacją. XmlPullParser na Androidzie analizuje XML w miarę czytania, nie ładując całego dokumentu do pamięci operacyjnej. Jest to krytyczne dla dużych odpowiedzi API, parsingu kanałów RSS z setkami elementów lub przetwarzania tablicy tysięcy obiektów JSON z serwerowego dumpa. Parser strumieniowy czyta token za tokenem, zużywając stałą ilość pamięci niezależnie od rozmiaru dokumentu.
JSON — dominujący format wymiany danych. Na iOS wbudowany JSONSerialization analizuje JSON do Any, a JSONDecoder — bezpośrednio do struktury Codable. Na Androidzie standardowy org.json udostępnia JSONObject i JSONArray do ręcznej analizy. Gson i Moshi dodają automatyczną konwersję. Wybór między ręcznym a automatycznym podejściem — pierwsza decyzja architektoniczna warstwy sieciowej.
val jsonString = """{"users":[{"id":1,"name":"Alice"}]}"""
val jsonObject = JSONObject(jsonString)
val usersArray = jsonObject.getJSONArray("users")
for (i in 0 until usersArray.length()) {
val item = usersArray.getJSONObject(i)
val id = item.getInt("id")
val name = item.getString("name")
// przetwarzanie użytkownika
}
Ręczny parsing przez org.json jest przydatny, gdy struktura odpowiedzi nie jest z góry znana lub znacznie się różni. Takie podejście daje pełną kontrolę nad obsługą błędów i nullable-polami, ale wymaga więcej kodu szablonowego w porównaniu z automatyczną deserializacją. W małych projektach lub prototypach jest to do przyjęcia, ale w production zaleca się Moshi lub kotlinx.serialization.
JsonReader z biblioteki Moshi — potężne narzędzie strumieniowego parsingu JSON. Czyta dokument token po tokenie, używając metod beginObject, nextName, nextString, nextInt i endObject. Takie podejście pozwala przetwarzać dokumenty dowolnego rozmiaru przy stałym zużyciu pamięci. Według danych Google (2026), strumieniowy parsing przez JsonReader jest 2–3 razy szybszy niż ładowanie całego dokumentu do JsonObject i zużywa do 80% mniej pamięci.
val reader = JsonReader(StringReader(json))
reader.beginObject()
while (reader.hasNext()) {
val name = reader.nextName()
when (name) {
"id" -> val id = reader.nextInt()
"name" -> val name = reader.nextString()
"email" -> val email = reader.nextString()
else -> reader.skipValue()
}
}
reader.endObject()
W przykładzie pokazano JsonReader, który analizuje JSON strumieniowo. Każde wywołanie nextName() i nextInt() przesuwa kursor na następny token. skipValue() pomija niepotrzebne pola bez ich analizowania — jest to szczególnie przydatne, gdy JSON zawiera 50 pól, a potrzebne są tylko 3. Rezultat — minimalne zużycie pamięci i maksymalna prędkość.
XML nadal jest używany w projektach Android do zasobów i w usługach SOAP aplikacji korporacyjnych. Na Androidzie wbudowany XmlPullParser zapewnia strumieniową analizę przy minimalnym zużyciu pamięci — nie ładuje drzewa DOM, ale generuje zdarzenia START_TAG, TEXT, END_TAG. iOS używa XMLParser z podejściem delegatów: metody parser(didStartElement:) i parser(foundCharacters:) przetwarzają elementy sekwencyjnie.
CSV — najprostszy format do eksportu i importu danych tabelarycznych. W aplikacjach mobilnych CSV jest używany do eksportu raportów, ładowania słowników (listy krajów, walut, kodów) i synchronizacji danych offline. Do parsingu CSV nadają się biblioteki strumieniowe: Apache Commons CSV i OpenCSV przetwarzają pliki linia po linii, escapując cudzysłowy i przecinki wewnątrz wartości. Na iOS parsing CSV można zrealizować przez delimiter NSString.components(separatedBy:) z obsługą przypadków brzegowych.
class CSVParser: NSObject, XMLParserDelegate {
private var currentItem: [String: String] = [:]
private var currentElement: String = ""
func parser(
_ parser: XMLParser,
didStartElement elementName: String,
namespaceURI: String?,
qualifiedName qName: String?,
attributes attributeDict: [String: String]
) {
currentElement = elementName
if elementName == "item" {
currentItem = [:]
}
}
func parser(_ parser: XMLParser,
foundCharacters string: String) {
currentItem[currentElement] = string
}
}
Przykład delegata XMLParser na iOS do analizy kanału RSS. Metoda didStartElement jest wywoływana przy każdym otwierającym tagu, foundCharacters zwraca zawartość tekstową między tagami, didEndElement kończy element. Taka architektura zdarzeniowa pozwala przetwarzać XML dowolnego rozmiaru bez ładowania drzewa DOM do pamięci — krytyczne dla ograniczonych zasobów urządzeń mobilnych.
Na Androidzie wybór parsera CSV zależy od objętości danych. OpenCSV obsługuje fluent API, adnotacje do mapowania na POJO i niestandardowe separatory. Apache Commons CSV — bardziej niskopoziomowy, ale szybszy na dużych plikach. W prostych przypadkach (1–2 kolumny) wystarczy ręczna analiza przez String.split(",") z obsługą escapowania. W projektach production z dużymi plikami CSV zaleca się OpenCSV.
Protocol Buffers od Google — binarny format serializacji, przewyższający JSON szybkością i kompaktowością. Wiadomość Protobuf zajmuje 3–6 razy mniej miejsca niż równoważny JSON i jest parsowana 4–10 razy szybciej dzięki binarnemu formatowi i sztywnemu schematowi. Główne wady: brak czytelności dla człowieka i konieczność generowania kodu z plików .proto przez kompilator protoc.
Strumieniowy parsing Protobuf jest realizowany przez CodedInputStream — klient czyta pola w miarę ich napływania bez ładowania całej wiadomości. Każde pole ma tag (numer + typ), a parser może pomijać nieznane pola. Według danych Google (2026), strumieniowa analiza Protobuf zużywa do 90% mniej pamięci przy przetwarzaniu wiadomości od 1 MB, co jest krytyczne dla urządzeń mobilnych z ograniczoną pamięcią RAM. Protobuf-lite — specjalna wersja dla Android, zoptymalizowana pod względem rozmiaru wygenerowanego kodu.
Często zadawane pytania
JSONSerialization — ręczny parsing, zwracający Any (Dictionary, Array) bez typizacji. JSONDecoder — automatyczna deserializacja do typów Codable. JSONSerialization daje elastyczność dla dynamicznych struktur, JSONDecoder — szybkość i bezpieczeństwo typów dla znanych schematów. W production zaleca się JSONDecoder.
Parsing strumieniowy jest obowiązkowy przy odpowiedziach od 500 KB, przy parsowaniu kanałów RSS/Atom i przy analizie plików na urządzeniach z ograniczoną pamięcią. Dla typowych odpowiedzi API do 100 KB automatyczna deserializacja przez JSONDecoder lub Moshi jest preferowana — kod jest czystszy i szybciej się go tworzy.
Android SDK zawiera org.json (JSONObject, JSONArray), XmlPullParser (XML) i android.util.JsonReader. Dla CSV, YAML i Protobuf wymagane są dodatkowe biblioteki: OpenCSV dla CSV, SnakeYAML dla YAML, protobuf-javalite dla Protobuf.
Użyj trybu lenient w kotlinx.serialization lub JsonReader.setLenient(true) w Moshi — wybacza zbędne przecinki, nieescapowane cudzysłowy i jednoliniowe komentarze. Dla pełnej walidacji wdróż testowanie kontraktowe przez Pact lub Spring Cloud Contract.
SAX (Simple API for XML) — strumieniowy parser XML, generujący zdarzenia startElement, characters, endElement podczas przeglądania dokumentu. Zaimplementowany przez XmlPullParser na Androidzie i XMLParser na iOS. Stosowany w czytnikach RSS, synchronizacji danych offline i przetwarzaniu plików SVG.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również