json

FormatValidateConvert

JSON to Swift

JSON
Language
Structured output

Result· read-only

—Swift

The result appears here.

Generate

JSON to Swift: generate Codable structs from JSON.

Your document never leaves the browser.

Swift Codable structs from a JSON sample — in your browser, never uploaded.

Paste the JSON your app receives and get structs that JSONDecoder fills in. The output targets Swift 5.9 and uses only the standard library and Foundation, so there is no package to add.

5.9

Swift, with only the standard library and Foundation

38

significant digits Decimal keeps past Int

0

bytes leave your machine

Structs and their CodingKeys

Each object becomes a struct conforming to Codable, with let properties in camelCase. When a key had to be renamed to fit Swift, the struct gets a CodingKeys enum mapping each property back to its JSON name, so order_id and placed_at still decode even though the properties are orderId and placedAt.

A key that is absent from some records, or null in some, becomes an optional. note is String? and gift-wrap is Bool?, spelled giftWrap in Swift. As the header comment says, a missing key and a null both decode as nil, and a nil value is left out when the struct is encoded again.

1

The sample, an order with two line items, pasted as the source

{
  "order_id": 1042,
  "placed_at": "2026-09-25T10:15:00Z",
  "paid": true,
  "customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
  "items": [
    { "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
    { "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
  ]
}
2

The structs written for it

// Generated by myjsoneditor.com for Codable (Swift 5.9+).
// A missing key and a null both decode as nil, and nil encodes as a missing key.

struct Customer: Codable {
  let name: String
  let email: String
}

struct Item: Codable {
  let sku: String
  let qty: Int
  let price: Double
  let note: String?
  let giftWrap: Bool?

  enum CodingKeys: String, CodingKey {
    case sku
    case qty
    case price
    case note
    case giftWrap = "gift-wrap"
  }
}

struct Root: Codable {
  let orderId: Int
  let placedAt: String
  let paid: Bool
  let customer: Customer
  let items: [Item]

  enum CodingKeys: String, CodingKey {
    case orderId = "order_id"
    case placedAt = "placed_at"
    case paid
    case customer
    case items
  }
}

The one option

Hashable, Sendable is off by default. Turn it on and every struct also conforms to Hashable, so it can go into a Set or serve as a dictionary key, and to Sendable, so it can cross an actor boundary under Swift’s strict concurrency checking.

1

An order id and a flag

{ "order_id": 1042, "paid": true }
2

With Hashable, Sendable on

// Generated by myjsoneditor.com for Codable (Swift 5.9+).
// A missing key and a null both decode as nil, and nil encodes as a missing key.

struct Root: Codable, Hashable, Sendable {
  let orderId: Int
  let paid: Bool

  enum CodingKeys: String, CodingKey {
    case orderId = "order_id"
    case paid
  }
}

Values Swift cannot type from a sample

A field that holds more than one type, or only ever null, is typed JSONValue, and the file includes that enum: a small Codable type with a case for null, a Boolean, a number, a string, an array and an object. Switch over it to read the value, or replace it with a concrete type once you know one.

A struct shape met twice in the document is written once. An integer larger than Int becomes Decimal, which keeps up to 38 significant digits exactly. A key that is a Swift keyword is escaped with backticks, so class is `class`, and a key starting with a digit gets an underscore in front.

  • A field that holds more than one type
  • only ever null
1

A mixed list and a 20-digit number

{ "code": [1, "A"], "account": 12345678901234567890 }
2

JSONValue, included in the file, and Decimal

// Generated by myjsoneditor.com for Codable (Swift 5.9+).
// A missing key and a null both decode as nil, and nil encodes as a missing key.
// Decimal keeps integers past Int exactly up to 38 significant digits; longer ones lose their last digits.

import Foundation

struct Root: Codable {
  let code: [JSONValue] // elements: one of: Int, String
  let account: Decimal // past Int — Decimal keeps 38 significant digits
}

enum JSONValue: Codable, Hashable, Sendable {
  case null
  case bool(Bool)
  case number(Decimal)
  case string(String)
  case array([JSONValue])
  case object([String: JSONValue])

  init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    if container.decodeNil() { self = .null }
    else if let value = try? container.decode(Bool.self) { self = .bool(value) }
    else if let value = try? container.decode(Decimal.self) { self = .number(value) }
    else if let value = try? container.decode(String.self) { self = .string(value) }
    else if let value = try? container.decode([JSONValue].self) { self = .array(value) }
    else { self = .object(try container.decode([String: JSONValue].self)) }
  }

  func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    switch self {
    case .null: try container.encodeNil()
    case .bool(let value): try container.encode(value)
    case .number(let value): try container.encode(value)
    case .string(let value): try container.encode(value)
    case .array(let value): try container.encode(value)
    case .object(let value): try container.encode(value)
    }
  }
}

Your sample stays here

Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.

Read next:

FAQ

Frequently asked questions

Didn’t find your answer?Write to us on the contact page →
How do I decode the JSON?

try JSONDecoder().decode(Root.self, from: data), with your root type in place of Root. The error it throws names the coding path that failed.

Can I use convertFromSnakeCase instead of CodingKeys?

Yes, for keys in snake_case; delete the CodingKeys enum and set the decoder’s keyDecodingStrategy. Keys such as gift-wrap still need an explicit mapping.

Why is price a Double and not a Decimal?

Double is what most apps expect for a price read from JSON. For money that must add up to the cent, change it to Decimal.

Keyboard shortcuts

Send feedback

Questions, bug reports and feature requests are all welcome. A bug report is easiest to act on with the shape of the document that caused it — never send anything confidential.

Email us

Contact page, in a new tab, so this page stays as it is.

Settings

Indent

The result is written with it — YAML and XML at 2 spaces when it is Tab.

Code text size
14 px

Both panes.

Wrap long lines

Load from a URL

Your browser fetches it directly — the request goes to that site, never to us.