Skip to content

Formatters & Code

JSON to Swift Codable

Swift Codable structs with CodingKeys when needed.

Runs in your browser
JSON · source
lines: 17chars: 261size: 261 B
Swift Codable · result
lines: 18chars: 317size: 317 B
live

Understanding JSON → Swift

Codable, and the small print.

Why a Swift JSON DTO is usually three lines, and the CodingKeys override that's almost always required.

Codable is two protocols.

Codable is a typealias for Encodable & Decodable — two protocols that, when conformed to, let the compiler synthesize JSON encoding and decoding automatically. Mark your type Codable and the compiler does the work; mark it Decodable only and you save the encode-side synthesis. For a typical DTO, struct User: Codable {...} is enough to encode and decode.

Convention mismatch — CodingKeys.

Swift convention is camelCase property names; JSON keys are typically snake_case. The synthesis matches names verbatim — user_id in JSON looks for a property called user_id in Swift, which violates the language style. The fix is either a global key-decoding strategy on the decoder (.convertFromSnakeCase) or a per-type CodingKeys enum that maps the names. The decoder strategy is cleaner if all of your DTOs follow the same convention; the per-type enum is needed when names can't be derived automatically.

A worked example.

From { "user_id": 7, "name": "Q", "avatar": null }: struct User: Codable { let userId: Int let name: String let avatar: String? enum CodingKeys: String, CodingKey { case userId = "user_id" case name, avatar } } Five lines of struct, three lines of CodingKeys. Or alternatively configure the decoder once: decoder.keyDecodingStrategy = .convertFromSnakeCase and drop the CodingKeys enum entirely.

With per-type CodingKeys

manual key map

Required when one or two keys diverge from convention.

enum CodingKeys: String, CodingKey { case userId = 'user_id' ... }

= Explicit mapping per property

With decoder strategy

decoder.keyDecodingStrategy = .convertFromSnakeCase

Set once on the JSONDecoder; applies to every type.

Drop the CodingKeys enum

= Cleaner DTOs

Optional vs implicitly-unwrapped.

A JSON field that's sometimes absent or null should be a Swift optional ( String?). Implicitly-unwrapped optionals (String!) work for "the value is always present after init, but I can't prove it to the compiler" — a pattern that has its place for outlets and post-init lifecycle but is wrong for JSON-decoded data. Use real optionals; rely on the type system to make absence explicit at the call site.

Dates and the date strategy.

Dates are the trickiest cross-language JSON field. Swift's Date can be encoded as ISO 8601, Unix epoch seconds, milliseconds, or a custom format. The decoder picks based on dateDecodingStrategy: .iso8601 is the right default for modern APIs. If the server is using a non-standard format, set a custom DateFormatter on the strategy. Get this wrong and every date in your data is silently shifted by hours or rejected entirely.

Custom decoding via init(from decoder:).

Synthesized decoding handles 95 % of cases. For the rest — fields that need transformation during decode, conditional logic on the JSON shape, polymorphic types that pick a subclass from a discriminator — implement init(from decoder: Decoder) throws by hand. The boilerplate is more than the synthesized version but you get full control. Codegen tools sometimes emit custom decode for tagged unions; for plain DTOs they always lean on synthesis.

Sendable on modern Swift.

Swift 5.5+ added Sendable — a marker protocol indicating a type is safe to pass across concurrency boundaries. Value types whose stored properties are also Sendable get the conformance automatically. Mark your DTOs struct User: Codable, Sendable and they work correctly with async/await and actors. Reference types, mutable shared state, and any class without explicit Sendable conformance need more thought.

Frequently asked questions

Quick answers.

Does this tool support snake_case to camelCase conversion?

Yes. If the input contains snake_case keys, the tool generates camelCase properties and an internal `CodingKeys` enum to map them correctly.

What happens with nested objects in the JSON?

Nested objects are extracted into their own individual structs. The tool creates a clean hierarchy that reflects the structure of your JSON payload.

Is my API schema sent to your servers?

No. The parsing logic is executed entirely on your local machine using JavaScript. Your JSON and the resulting Swift code are never transmitted to our servers.

How does it handle optional values or nulls?

Properties are marked as Optional if a value is null in the sample JSON. For more robust models, ensure your sample JSON represents the maximum possible data structure.

People also search for

Related tools

More in this room.

See all in Formatters & Code