JSON обработка в Swift: Codable, JSONSerialization, SwiftJSON

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

JSON обработка в Swift (iOS/macOS): Полное руководство

JSON (JavaScript Object Notation) — основной формат обмена данными в современных iOS/macOS приложениях. Swift предоставляет мощный набор инструментов для работы с JSON, начиная от встроенных протоколов Codable и заканчивая сторонними библиотеками, упрощающими парсинг и сериализацию. В этой статье мы подробно разберём все основные способы обработки JSON в Swift для платформ Apple.

Встроенная поддержка JSON: Codable (Swift 4+)

Начиная с Swift 4, Apple представила протоколы Codable (объединяющий Encodable и Decodable), которые позволяют автоматически преобразовывать пользовательские типы данных в JSON и обратно без написания boilerplate кода.

Базовый пример декодирования JSON

import Foundation

// 1. Определяем модель данных
struct User: Codable {
    let id: Int
    let name: String
    let email: String
    let isActive: Bool
}

// 2. JSON-строка
let jsonString = """
{
    "id": 1,
    "name": "Иван Петров",
    "email": "ivan@example.com",
    "isActive": true
}
"""

// 3. Декодируем
if let jsonData = jsonString.data(using: .utf8) {
    let decoder = JSONDecoder()
    do {
        let user = try decoder.decode(User.self, from: jsonData)
        print("Пользователь: \(user.name), email: \(user.email)")
    } catch {
        print("Ошибка декодирования: \(error.localizedDescription)")
    }
}

Кодирование объекта в JSON

let newUser = User(id: 2, name: "Мария Сидорова", email: "maria@example.com", isActive: false)

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // для читаемого вывода

do {
    let jsonData = try encoder.encode(newUser)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
} catch {
    print("Ошибка кодирования: \(error)")
}

Работа с ключами в snake_case и кастомные стратегии

Часто JSON приходит с ключами в стиле snake_case (например, first_name), а Swift-свойства пишутся в camelCase (firstName). Это решается одной строкой:

decoder.keyDecodingStrategy = .convertFromSnakeCase
encoder.keyEncodingStrategy = .convertToSnakeCase

JSONSerialization — низкоуровневая работа

Для случаев, когда структура JSON неизвестна заранее или требуется гибкость, используется JSONSerialization из Foundation:

if let jsonData = jsonString.data(using: .utf8) {
    do {
        if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
            let name = jsonDict["name"] as? String ?? ""
            let age = jsonDict["age"] as? Int ?? 0
            print("Имя: \(name), Возраст: \(age)")
        }
    } catch {
        print("Ошибка: \(error)")
    }
}

Этот метод возвращает Any, поэтому требуется приведение типов. Подходит для динамических данных, но менее безопасен по типам.

Сторонние библиотеки

Несмотря на мощь встроенных средств, существуют популярные библиотеки, упрощающие работу с JSON в Swift:

1. SwiftyJSON

Одна из самых популярных библиотек. Позволяет обращаться к элементам JSON через подписки (subscripts) и автоматически обрабатывает опциональные значения.

// Установка через Swift Package Manager: https://github.com/SwiftyJSON/SwiftyJSON
import SwiftyJSON

let json = JSON(parseJSON: jsonString)
let userName = json["name"].stringValue
let userEmail = json["email"].string ?? "не указан"
print("Имя: \(userName), Email: \(userEmail)")

// Работа с вложенными объектами
let address = json["address"]["city"].stringValue

2. ObjectMapper

Библиотека для маппинга JSON в объекты и обратно. Требует ручного описания преобразований, но даёт полный контроль.

import ObjectMapper

class UserModel: Mappable {
    var id: Int?
    var name: String?
    
    required init?(map: Map) {}
    
    func mapping(map: Map) {
        id   <- map["id"]
        name <- map["name"]
    }
}

if let user = UserModel(JSONString: jsonString) {
    print(user.name ?? "")
}

3. Codable + Combine (iOS 13+)

Для асинхронной работы с JSON в связке с сетевыми запросами:

import Combine

var cancellables = Set<AnyCancellable>()

let url = URL(string: "https://api.example.com/users")!
URL                    

Рекомендаций