JSONSerialization: co to jest, metody klasy Foundation i jak działa

Autor: IT Sectr Opublikowano: 2026-03-15 Czas czytania: 8 min

JSONSerialization — wbudowana klasa iOS z frameworka Foundation, przeznaczona do konwersji JSON na obiekty Foundation i odwrotnie. To API jest podstawowym mechanizmem pracy z JSON na platformach Apple bez podłączania zewnętrznych bibliotek, obsługując parsowanie słowników, tablic i typów prymitywnych. Według Apple Developer, 2024, JSONSerialization obsługuje pracę z Data, strumieniami i opcjami odczytu dla elastycznego przetwarzania danych JSON.

Najważniejsze

  • JSONSerialization — wbudowana klasa Foundation do parsowania JSON na iOS i macOS
  • jsonObject — metoda konwersji danych JSON na słowniki i tablice Foundation
  • data — metoda serializacji obiektów Foundation z powrotem do danych JSON
  • isValidJSONObject — sprawdzenie, czy obiekt może być serializowany do JSON
  • Codable — nowoczesna alternatywa z typowaną serializacją w Swift

Co to jest JSONSerialization

JSONSerialization — to klasa z frameworka Foundation, dostępna na iOS, macOS, tvOS i watchOS. Udostępnia metody do konwersji danych JSON na obiekty Foundation (NSDictionary, NSArray, NSString, NSNumber) i odwrotnie. Klasa pojawiła się w iOS 5 i do wprowadzenia Codable (Swift 4) pozostawała głównym sposobem pracy z JSON na platformach Apple. Pomimo wieku, JSONSerialization pozostaje popularny w legacy-projektach na Objective-C oraz w scenariuszach wymagających dynamicznego przetwarzania JSON bez stałego schematu modelu.

Kiedy stosuje się JSONSerialization

Pomimo pojawienia się Codable, JSONSerialization pozostaje aktualny w kilku scenariuszach. Dynamiczna struktura JSON — gdy format odpowiedzi zmienia się lub jest z góry nieznany — wymaga dostępu do słowników przez klucze, co łatwiej zrobić przez JSONSerialization. Klasa jest również stosowana w projektach Objective-C, gdzie Codable jest niedostępny, oraz przy pracy ze strumieniami do etapowego parsowania dużych plików JSON. W testach i makietach isValidJSONObject i data(withJSONObject:options:) pozwalają szybko generować JSON-fixtury bez podłączania zewnętrznych bibliotek, co przyspiesza rozwój i prototypowanie.

swift
import Foundation

// Podstawowa struktura użycia 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("Błąd parsowania JSON: \(error)")
}

Główne metody klasy

JSONSerialization udostępnia cztery główne metody do pracy z JSON. Główna metoda — jsonObject(with:options:), która konwertuje Data na obiekty Foundation. Metoda data(withJSONObject:options:) wykonuje serializację zwrotną. isValidJSONObject(_:) sprawdza, czy obiekt może być serializowany. writeJSONObject(_:to:options:error:) zapisuje JSON bezpośrednio do strumienia. Do odczytu JSON z InputStream istnieje metoda jsonObject(with:options:), przyjmująca strumień zamiast Data, co jest wygodne przy integracji z zapytaniami sieciowymi zwracającymi dane strumieniowe.

JSONObject i JSONData

Metoda jsonObject przyjmuje Data i zwraca Any — zazwyczaj NSDictionary lub NSArray. Do bezpiecznej pracy wynik jest rzutowany na oczekiwany typ przez rzutowanie warunkowe. Metoda data przyjmuje obiekt Foundation i zwraca Data z reprezentacją JSON. Opcja .prettyPrinted dodaje formatowanie z wcięciami dla czytelności.

swift
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)")
        }
    }
}

// Deserializacja zwrotna: obiekt -> JSON
let outputDict: [String: Any] = ["status": "ok", "count": 42]
if let outputData = try? JSONSerialization
    .data(withJSONObject: outputDict,
                options: .prettyPrinted) {
    String(data: outputData, encoding: .utf8)
}

Przykłady parsowania JSON

Podstawowe parsowanie słownika z typami prymitywnymi — to najczęstsza operacja z JSONSerialization. Po otrzymaniu Data przez URLSession programista wywołuje jsonObject i rzutuje wynik na oczekiwany typ. Dla tablic obiektów stosuje się rzutowanie na [[String: Any]], po czym każdy element jest przetwarzany w pętli. Takie podejście jest elastyczne, ale wymaga ręcznego zarządzania typami.

Parsowanie zagnieżdżonych struktur

Rzeczywiste API zwracają złożone zagnieżdżone obiekty JSON z tablicami, datami i polami opcjonalnymi. JSONSerialization poprawnie obsługuje dowolny poziom zagnieżdżenia, ale programista musi samodzielnie rzutować każdy poziom na wymagany typ. Aby uprościć to zadanie, Apple zaleca stosowanie Codable dla danych typowanych, a JSONSerialization — tylko dla struktur dynamicznych.

swift
// Parsowanie odpowiedzi 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żytkownik: \(name) (ID: \(userId))")

    } catch let error as ParsingError {
        print("Parsowanie nie powiodło się: \(error)")
    } catch {
        print("Nieoczekiwany błąd: \(error)")
    }
}

enum ParsingError: Error {
    case missingField
    case invalidType
}

Obsługa błędów

JSONSerialization zgłasza błędy przy nieprawidłowym JSON, niezgodności typów lub przekroczeniu głębokości zagnieżdżenia. Błędy należą do typu CocoaError i zawierają kod z opisem problemu. Programista jest zobowiązany do ich obsługi przez konstrukcję do-catch, w przeciwnym razie aplikacja zakończy się awaryjnie. Najczęstsze błędy: NSPropertyListReadCorruptError (nieprawidłowy JSON) i NSPropertyListReadUnknownError. Każdy typ błędu wymaga własnej strategii obsługi: przy nieprawidłowym formacie należy zażądać ponownego wysłania danych, a przy niezgodności struktury — zaktualizować model parsowania.

Typy błędów przy deserializacji

Nieprawidłowy JSON — najczęstsza przyczyna awarii: brakujący przecinek, zbędny znak lub nieprawidłowo escaped cudzysłów łamią całe parsowanie. Drugi typ błędów — niezgodność z oczekiwaną strukturą: na przykład serwer zwrócił tablicę zamiast słownika. JSONSerialization.fragmentsAllowed pozwala odczytywać JSON, którego korzeniem nie jest słownik lub tablica, ale wartość prymitywna. Programista może również napotkać błąd przekroczenia głębokości zagnieżdżenia, gdy JSON zawiera zbyt wiele poziomów hierarchii.

Opcje odczytu i zapisu

JSONSerialization udostępnia kilka opcji do konfiguracji parsowania. .mutableContainers zwraca NSMutableDictionary i NSMutableArray zamiast niezmiennych wersji, co jest przydatne przy modyfikacji danych po parsowaniu. .mutableLeaves czyni modyfikowalnymi wartości tekstowe. .fragmentsAllowed zezwala na JSON, którego korzeniem nie jest obiekt lub tablica, a tekst lub liczba — to wygodne dla prostych odpowiedzi API. Opcje .withoutEscapingSlashes i .sortedKeys są dostępne dla metody data(withJSONObject:options:), sterując formatowaniem serializowanego JSON. Opcje są przekazywane maską bitową, co pozwala łączyć wiele wartości przez operator | dla elastycznej konfiguracji parsowania.

swift
// Obsługa różnych typów błędów
func safeParse(jsonData: Data) {
    do {
        let object = try JSONSerialization
            .jsonObject(with: jsonData,
                           options: .fragmentsAllowed)

        if let dictionary = object as? [String: Any] {
            print("Słownik z \(dictionary.count) kluczami")
        } else if let array = object as? [Any] {
            print("Tablica z \(array.count) elementami")
        }

    } catch CocoaError.propertyListReadCorrupt {
        print("Uszkodzone dane JSON")
    } catch let error as CocoaError {
        print("Błąd Cocoa: \(error)")
    } catch {
        print("Nieznany błąd: \(error)")
    }
}

// Sprawdzanie poprawności obiektu przed serializacją
let testObject: [String: Any] = ["key": "value", "nested": ["a": 1]]
if JSONSerialization.isValidJSONObject(testObject) {
    print("Poprawny obiekt JSON")
}

Na wydajność JSONSerialization wpływa rozmiar danych i częstotliwość wywołań. Przy jednokrotnym parsowaniu małej odpowiedzi serwera różnica jest niezauważalna, ale przy przetwarzaniu dziesiątek megabajtów JSON lub częstych wywołaniach w pętlach warto uwzględnić narzut na rzutowanie typów. JSONSerialization działa synchronicznie w bieżącym wątku, dlatego dla dużych dokumentów zaleca się przeniesienie parsowania do kolejki tła przez DispatchQueue.global(). Alternatywnie można użyć InputStream do przetwarzania strumieniowego bez ładowania całego pliku do pamięci, co jest krytyczne dla aplikacji z ograniczonymi zasobami. Do zapisu JSON do pliku lub strumienia sieciowego metoda writeJSONObject(_:to:options:error:) pozwala bezpośrednio kierować serializowane dane do OutputStream bez tworzenia pośredniego obiektu Data, co zmniejsza zużycie pamięci przy pracy z dużymi dokumentami.

Często zadawane pytania

Co to jest JSONSerialization w iOS?

JSONSerialization — to klasa Foundation do konwersji danych JSON na obiekty Foundation (NSDictionary, NSArray) i odwrotnie. Działa na iOS, macOS, tvOS i watchOS bez podłączania dodatkowych bibliotek.

Czym JSONSerialization różni się od Codable?

Codable — to protokół Swift do automatycznej typowanej serializacji, który kompiluje się w typowo bezpieczny kod. JSONSerialization pracuje z dynamicznymi typami Any i wymaga ręcznego rzutowania. Codable jest preferowany dla nowych projektów, JSONSerialization — dla Objective-C i danych dynamicznych.

Jak obsłużyć błąd podczas parsowania JSON?

Użyj konstrukcji do-catch przy wywołaniu jsonObject. Błędy JSONSerialization należą do CocoaError. Do debugowania sprawdzaj NSPropertyListReadCorruptError, który wskazuje na nieprawidłowy format danych JSON.

Czy JSONSerialization obsługuje zagnieżdżone struktury?

Tak, JSONSerialization obsługuje dowolny poziom zagnieżdżenia słowników i tablic. Wszystkie zagnieżdżone obiekty są konwertowane na odpowiadające typy Foundation (NSDictionary, NSArray, NSString, NSNumber), zachowując oryginalną strukturę JSON.

Kiedy stosować JSONSerialization zamiast Codable?

JSONSerialization jest odpowiedni przy dynamicznej strukturze JSON, w projektach Objective-C, przy pracy ze strumieniami i do sprawdzania poprawności JSON przez isValidJSONObject. Dla typowanych struktur ze znanym schematem preferowany jest Codable.

Podsumowanie

  • JSONSerialization — wbudowana klasa Foundation do podstawowej pracy z JSON na platformach Apple
  • jsonObject — główna metoda parsowania, konwertująca Data na słowniki i tablice Foundation
  • data — metoda serializacji zwrotnej obiektów Foundation do danych JSON z opcjami formatowania
  • isValidJSONObject — predykat do sprawdzania możliwości serializacji obiektu do JSON
  • Obsługa błędów jest obowiązkowa przez do-catch w celu zapobiegania awaryjnemu zakończeniu aplikacji
  • Codable — nowoczesna typowana alternatywa dla projektów Swift ze znanym schematem danych

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.

Omów projekt

Przeczytaj również