Skip to main content

JSON to Swift Codable — struct or class, CodingKeys, Optionals

JSON to Swift Codable — paste JSON, get struct or class types conforming to Codable, camelCase properties, a CodingKeys enum for non-matching keys, Optional T? for nullable fields, and nested types.

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
Examples:
How types, CodingKeys & Optionals are inferred

Each JSON object becomes a Swift type conforming to Codable, with camelCase properties; nested objects lift into their own named types (User.address → UserAddress). When the Swift property name differs from the wire key (snake_case, kebab-case, a reserved word), a CodingKeys enum maps the property back to the exact JSON key so JSONDecoder round-trips. When every key already matches, the CodingKeys enum is omitted — Swift synthesises it for you (turn on "Always emit CodingKeys" to document the contract anyway). Integer numbers infer Int; fractional numbers infer Double; a number that is sometimes whole and sometimes fractional widens to Double. Arrays of objects fold into ONE type — keys missing from some elements (or seen as null) become Optional (T?). A value that is only ever null types as AnyCodable? — Swift's Any is not Codable, so the output flags a placeholder you replace with your own type-erased wrapper. Switch struct↔class and let↔var to match your model style.

What this tool does

Paste any JSON payload — a URLSession response, a Vapor route body, a Firebase document, a third-party REST API — and get back a clean set of Swift types conforming to `Codable`, ready to drop into a `.swift` file and decode with `JSONDecoder`. Properties are generated as `let` (immutable by default, the right choice for a decoded model) or `var` if you toggle it, JSON keys are camelCased into valid identifiers (`site_admin` becomes `siteAdmin`, `created_at` becomes `createdAt`, `first-name` becomes `firstName`), and type names are PascalCased. When the Swift property name diverges from the wire key, a `CodingKeys: String, CodingKey` enum maps the property back to the exact JSON key so `JSONDecoder` round-trips without a custom `keyDecodingStrategy`; when every key already matches, the enum is omitted so Swift synthesises it for you — flip "Always emit CodingKeys" on if you want the wire contract documented in the type anyway. Numbers are split, not flattened: an integer-valued sample infers `Int`, a fractional value infers `Double`, and a field that is whole in one sample and decimal in another widens to `Double`. Nullability follows Swift's `Optional` precisely — a key that is missing from some elements of a JSON array, or seen as JSON `null`, becomes `T?`, and a value that is only ever null surfaces as `AnyCodable?` with a note, since Swift's `Any` is not `Codable`. Arrays of objects fold into ONE shared type, so `[{"a":1},{"a":1,"b":2}]` produces a single struct with both fields (and `b` Optional), not two near-duplicates. Nested objects lift into their own named types (`User.address` becomes `UserAddress`), you can switch `struct` to `class` to match a reference-semantics model, and reserved-word keys like `default` are backtick-escaped so the output always compiles. Everything runs in your browser — the JSON never touches a server.

Tool details

Input
Text + Numbers + Structured content
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy + Download
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
Shareable URL state
Key settings are encoded in the URL so another person can reopen the same setup.
Performance budget
Initial JS <= 25 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How JSON to Swift Codable fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 JSON to Kotlin Data Class JSON to Kotlin data class — paste JSON, get val properties, camelCase fields, nullable T?, nested classes, and kotlinx.serialization @SerialName, Gson @SerializedName, or Moshi @Json annotations. Open
  2. 2 JSON to TypeScript Interface JSON to TypeScript interface — paste JSON, get clean interfaces with union types from arrays, optional vs required detection, root name customizable. Open
  3. 3 JSON to Java Class JSON to Java POJO, record, or Lombok @Data — paste JSON, get camelCase fields with getters/setters, Jackson @JsonProperty or Gson @SerializedName, nested classes, primitive vs boxed inference. Open

Real-world use cases

  • Type a URLSession response without hand-writing the model

    You're decoding a third-party REST API in an iOS app and the response has 25+ fields in snake_case. Curl it once, paste the JSON here, set the root name to `OrderResponse`, keep struct + let. Every `created_at`-style key gets a `CodingKeys` entry so `JSONDecoder` binds it, nested objects lift into their own types, and optional fields become `T?`. Drop the output into `OrderResponse.swift`, call `try JSONDecoder().decode(OrderResponse.self, from: data)`, and you get a fully-typed result instead of digging through `[String: Any]` with force-casts that crash at runtime.

  • Build a request and response model for a Vapor route

    You're writing a Vapor backend and need `Content`-conforming models for a new endpoint. Paste the sample request body, name the root `CreateOrderRequest`, keep struct. You get a `Codable` struct with the right `CodingKeys` for any snake_case keys; add `: Content` to the declaration and Vapor decodes the request body straight into it. Turn on "Default Optionals to = nil" so missing optional fields don't break construction, and the model stays forward-compatible as the payload grows.

  • Catch which API fields are actually optional

    An endpoint sometimes includes `cancelled_at` and sometimes omits it. Capture a few responses, paste them as a JSON array, and the array-fold detection marks `cancelled_at` as missing in some elements — so it becomes `String?` instead of a non-Optional field that throws `keyNotFound` during decode. In your view code `if let cancelledAt` now cleanly distinguishes "cancelled" from "still active" instead of crashing the moment the key is absent.

  • Replace [String: Any] with a real Codable type

    Legacy Swift does `let json = try JSONSerialization.jsonObject(...) as? [String: Any]` and reaches in with `json?["id"] as? String`, losing every compile-time check and inviting silent nil from a typo'd key. Capture one representative response, paste it, generate the struct, and decode with `JSONDecoder`. Now `Int` and `Double` are inferred per field, Optionality is explicit, and the compiler catches a renamed key at build time instead of returning nil in production.

  • Generate a class model for a shared, mutable object

    You have a model that's shared across several SwiftUI views and mutated in place — a reference type is the right tool. Paste the JSON, switch struct to class and let to var, and you get a `class: Codable` with mutable `var` properties. Pair it with `@Observable` (or `ObservableObject`) and the same decoded type drives your view state directly, no separate view model boilerplate to keep in sync.

Common pitfalls

  • Pasting a single object and expecting some fields to be Optional. A single object has no missing-key signal, so every field is non-Optional unless its value is literally null. Optional inference only kicks in across a JSON array where some elements carry a key and others don't. To explore optionality from one sample, wrap it as `[{...}]`.

  • Leaving a money or precise-decimal field as `Double`. The tool infers `Double` for any fractional number, but `Double` is binary floating point and misrepresents values like 0.1 or a currency total. For money, change those fields to `Decimal` after generating — JSON carries no signal that a number needs exact base-10 precision.

  • Deleting a CodingKeys case and expecting decoding to still work. The enum is what maps `site_admin` (wire) to `siteAdmin` (property). Remove the case and JSONDecoder looks for a `siteAdmin` key that doesn't exist, throwing keyNotFound. Keep the case, or set decoder.keyDecodingStrategy = .convertFromSnakeCase globally instead of per-type CodingKeys.

  • Shipping the AnyCodable placeholder as-is. A field that was only ever null types as `AnyCodable?`, and `AnyCodable` is not a built-in Swift type — the output flags this in a comment. Either add a type-erased wrapper (the Flight-School/AnyCodable package is the common one) or replace it with the concrete `T?` once you know the real shape.

Privacy

Your JSON never leaves this browser tab. Parsing and type inference use the browser's built-in `JSON.parse`; there is no network call and no analytics on the textarea content. The Share link encodes your input and the root type name into the URL so a result is reproducible — that means YOU decide when to share. If the payload is sensitive (internal IDs, customer data, prod responses), copy the generated Swift instead of sharing the link. Only your option choices (struct vs class, let vs var, the CodingKeys and = nil toggles) are stored in localStorage so your preferred style persists across visits.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-06-13