← Назад к вопросам

Как парсишь JSON?

1.0 Junior🔥 221 комментариев
#Работа с сетью#Язык Swift

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разбор JSON в iOS: Основные подходы и практические примеры

В iOS разработке существует несколько основных способов парсинга JSON, каждый из которых имеет свои преимущества и подходит для разных задач.

Нативные инструменты от Apple: JSONSerialization

JSONSerialization (ранее известный как NSJSONSerialization) — это фундаментальный API, предоставляемый Foundation. Он работает с базовыми типами данных (Dictionary, Array, String, Number, Bool, Null).

Пример использования:

import Foundation

struct Product {
    let id: Int
    let name: String
    let price: Double
}

func parseJSONWithSerialization(jsonString: String) -> [Product]? {
    guard let data = jsonString.data(using: .utf8) else { return nil }
    
    do {
        let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
        
        if let jsonArray = jsonObject as? [[String: Any]] {
            var products: [Product] = []
            
            for item in jsonArray {
                guard let id = item["id"] as? Int,
                      let name = item["name"] as? String,
                      let price = item["price"] as? Double else { continue }
                
                products.append(Product(id: id, name: name, price: price))
            }
            return products
        }
    } catch {
        print("Ошибка парсинга JSON: \(error.localizedDescription)")
    }
    return nil
}

Преимущества этого метода:

  • Низкоуровневый контроль процесса
  • Не требует дополнительных зависимостей
  • Подходит для простых и нерегулярных структур данных

Недостатки:

  • Обилие опциональных проверок (as?)
  • Риск ошибок при типизации
  • Отсутствие автоматического маппинга на модели данных

Современный стандарт: Codable Protocol

В Swift 4 появилась революционная система Codable (комбинация Decodable и Encodable), которая автоматически конвертирует JSON в Swift структуры и классы.

Пример с Codable:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
    let isActive: Bool
    
    // Кастомное маппинг ключей JSON
    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case email
        case isActive = "active"
    }
}

func parseJSONWithCodable(jsonData: Data) -> User? {
    do {
        let decoder = JSONDecoder()
        // Можно настроить поведение парсинга
        decoder.keyDecodingStrategy = .convertFromSnakeCase // конвертирует snake_case в camelCase
        decoder.dateDecodingStrategy = .iso8601 // парсинг дат
        
        let user = try decoder.decode(User.self, from: jsonData)
        return user
    } catch let decodingError as DecodingError {
        switch decodingError {
        case .typeMismatch(let type, let context):
            print("Type mismatch for \(type): \(context.debugDescription)")
        case .valueNotFound(let type, let context):
            print("Value not found for \(type): \(context.debugDescription)")
        case .keyNotFound(let key, let context):
            print("Key '\(key.stringValue)' not found: \(context.debugDescription)")
        case .dataCorrupted(let context):
            print("Data corrupted: \(context.debugDescription)")
        default:
            print("Unknown decoding error")
        }
        return nil
    } catch {
        print("Общая ошибка: \(error.localizedDescription)")
        return nil
    }
}

Ключевые преимущества Codable:

  • Автоматическое маппинг через компилятор Swift
  • Высокая безопасность типов
  • Поддержка кастомных трансформаций через CodingKeys и свойств
  • Интроспекция ошибок через DecodingError контекст
  • Нативная интеграция со Swift типами (даты, URL, Decimal)

Дополнительные библиотеки и подходы

Для сложных случаев можно использовать:

  • Custom JSON Parsers: Для специфичных форматов или требований к производительности
  • Third-party Libraries: В прошлом часто использовались SwiftyJSON, ObjectMapper (но сейчас Codable покрывает большинство потребностей)

Практические рекомендации

  1. Codable является стандартом для большинства случаев благодаря безопасности, выразительности и производительности.
  2. JSONSerialization полезен для:
    • Динамических JSON структур без фиксированной схемы
    • Промежуточного разбора перед фильтрацией данных
    • Обработки JSON в Objective-C коде
  3. Обработка ошибок должна быть детализированной, особенно в Codable через анализ DecodingError.
  4. Асинхронный парсинг больших JSON файлов должен выполняться в фоновых потоках для избежания блокировки UI.
  5. Оптимизация памяти: Для очень больших JSON рекомендуется использовать инкрементальный парсинг или stream-based подходы.

Пример асинхронного парсинга с Codable в современном Swift:

func fetchAndParseJSON<T: Decodable>(url: URL, completion: @escaping (Result<T, Error>) -> Void) {
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        
        guard let data = data else {
            completion(.failure(NetworkError.noData))
            return
        }
        
        do {
            let decodedObject = try JSONDecoder().decode(T.self, from: data)
            completion(.success(decodedObject))
        } catch {
            completion(.failure(error))
        }
    }.resume()
}

Выбор метода парсинга зависит от конкретного контекста: сложности структуры данных, требований к производительности, необходимости динамического разбора и архитектурных предпочтений проекта.