Конвертер JSON в Swift Codable
Генерируйте из JSON структуры Swift, соответствующие протоколу Codable, с удобными инициализаторами для декодирования.
Генерация структур Swift Codable из JSON
Codable — стандартный способ декодировать JSON в Swift, но писать структуры моделей для объёмных данных утомительно. Конвертер генерирует для каждого объекта структуру, соответствующую Codable, со свойствами let типов Int, Double, String, Bool, вложенными структурами и массивами. Он добавляет перечисление CodingKeys, если ключ JSON отличается от имени свойства в Swift, а также расширения с инициализаторами для декодирования из Data, строки JSON или URL, метод with(...) для создания изменённых копий и jsonData()/jsonString() для обратного кодирования.
Как пользоваться
- Вставьте пример JSON — например, ответ, который получает ваше приложение для iOS или macOS.
- Введите имя корневого типа, например Article.
- Добавьте файл в проект Xcode и декодируйте данные через try Article(jsonString) или JSONDecoder().decode(Article.self, from: data).
Часто задаваемые вопросы
- Работает ли это со SwiftUI и URLSession?
- Да. Структуры — обычные типы-значения Codable, поэтому можно декодировать Data, полученные от URLSession, и передавать результат в представления SwiftUI, как любую другую модель.
- Как обрабатываются ключи в snake_case?
- Свойства получают имена в стиле Swift — camelCase (is_featured становится isFeatured), а перечисление CodingKeys сопоставляет каждое из них с исходным ключом JSON, так что настраивать keyDecodingStrategy не нужно.
- Можно ли удалить вспомогательные расширения?
- Да. Для Codable нужны только объявления структур и CodingKeys. Расширения и вспомогательные функции newJSONDecoder/newJSONEncoder — необязательные удобства, которые можно удалить.
Пример: JSON в Swift
Исходный JSON
{
"id": 3,
"title": "Hello Swift",
"author": { "name": "Taylor", "followers": 1200 },
"is_featured": true
}Сгенерированный код: Swift (Article)
// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
// let article = try Article(json)
import Foundation
// MARK: - Article
struct Article: Codable {
let id: Int
let title: String
let author: Author
let isFeatured: Bool
enum CodingKeys: String, CodingKey {
case id, title, author
case isFeatured = "is_featured"
}
}
// MARK: Article convenience initializers and mutators
extension Article {
init(data: Data) throws {
self = try newJSONDecoder().decode(Article.self, from: data)
}
init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
id: Int? = nil,
title: String? = nil,
author: Author? = nil,
isFeatured: Bool? = nil
) -> Article {
return Article(
id: id ?? self.id,
title: title ?? self.title,
author: author ?? self.author,
isFeatured: isFeatured ?? self.isFeatured
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Author
struct Author: Codable {
let name: String
let followers: Int
}
// MARK: Author convenience initializers and mutators
extension Author {
init(data: Data) throws {
self = try newJSONDecoder().decode(Author.self, from: data)
}
init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
name: String? = nil,
followers: Int? = nil
) -> Author {
return Author(
name: name ?? self.name,
followers: followers ?? self.followers
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Helper functions for creating encoders and decoders
func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
decoder.dateDecodingStrategy = .iso8601
}
return decoder
}
func newJSONEncoder() -> JSONEncoder {
let encoder = JSONEncoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
encoder.dateEncodingStrategy = .iso8601
}
return encoder
}