JSON to Swift Codable Converter

Generate Swift structs conforming to Codable from JSON, with convenience initializers for decoding.

Generate Swift Codable structs from JSON

Codable is the standard way to decode JSON in Swift, but writing the model structs for a large payload is tedious. This converter generates a struct conforming to Codable for each object, with let properties typed as Int, Double, String, Bool, nested structs and arrays. It adds a CodingKeys enum when a JSON key differs from the Swift property name, plus extensions with initializers that decode from Data, a JSON String or a URL, a with(...) method for making modified copies, and jsonData()/jsonString() for encoding back.

How to use

  1. Paste a JSON sample, such as the response your iOS or macOS app receives.
  2. Enter the root type name, for example Article.
  3. Add the file to your Xcode project and decode with try Article(jsonString) or JSONDecoder().decode(Article.self, from: data).

Frequently asked questions

Does it work with SwiftUI and URLSession?
Yes. The structs are plain Codable value types, so you can decode the Data returned by URLSession and pass the result to SwiftUI views like any other model.
How are snake_case keys handled?
Properties get Swift-style camelCase names (is_featured becomes isFeatured), and a CodingKeys enum maps each one to the original JSON key, so you do not need to set keyDecodingStrategy.
Can I remove the convenience extensions?
Yes. Only the struct declarations and CodingKeys are needed for Codable. The extensions and the newJSONDecoder/newJSONEncoder helpers are optional conveniences you can delete.

Example: JSON to Swift

Input JSON

{
  "id": 3,
  "title": "Hello Swift",
  "author": { "name": "Taylor", "followers": 1200 },
  "is_featured": true
}

Generated 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
}

Convert JSON to other languages