json

FormatValidateConvert

JSON to Kotlin

JSON
Language
Structured output

Result· read-only

—Kotlin

The result appears here.

Generate

JSON to Kotlin: generate data classes from JSON.

Your document never leaves the browser.

Kotlin data classes for kotlinx.serialization, from a JSON sample — in your browser.

Paste a payload and get data classes ready for kotlinx.serialization on Kotlin 2.0 or later. They work the same on Android, the JVM and Kotlin Multiplatform, since the library runs on all three. The module needs the Kotlin serialization compiler plugin, as any @Serializable class does.

2.0+

Kotlin, on Android, the JVM and Multiplatform

= null

marks a key that may be absent; T? alone may be null

0

bytes leave your machine

Absent and null are different things

Each object becomes a @Serializable data class with val properties in camelCase, and each renamed key keeps its wire name in @SerialName, so order_id is orderId. Whole numbers are Long and numbers with a fraction Double.

Kotlin’s default Json configuration can tell a missing key from a null one, and the output uses that. note is present in both line items and null in one, so it is String? with no default: the key must be there. gift-wrap is absent from one, so it is Boolean? = null, which may be left out. The header comment spells out the same rule.

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": "[email protected]" },
  "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 data classes written for it

// Generated by myjsoneditor.com for kotlinx.serialization (Kotlin 2.0+).
// Decode with the default Json: explicitNulls = true, so a `T?` with no default is a
// required key that may be null, and `T? = null` is a key that may be absent.

package generated

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class Customer(
  val name: String,
  val email: String,
)

@Serializable
data class Item(
  val sku: String,
  val qty: Long,
  val price: Double,
  val note: String?,
  @SerialName("gift-wrap")
  val giftWrap: Boolean? = null,
)

@Serializable
data class Root(
  @SerialName("order_id")
  val orderId: Long,
  @SerialName("placed_at")
  val placedAt: String,
  val paid: Boolean,
  val customer: Customer,
  val items: List<Item>,
)

Options

The sample, with Serialization annotations off

// Generated by myjsoneditor.com as plain Kotlin data classes (Kotlin 2.0+).
// Add your JSON library's annotations; `T? = null` marks a key that may be absent.

package generated

data class Customer(
  val name: String,
  val email: String,
)

data class Item(
  val sku: String,
  val qty: Long,
  val price: Double,
  val note: String?,
  val giftWrap: Boolean? = null, // JSON key: "gift-wrap"
)

data class Root(
  val orderId: Long, // JSON key: "order_id"
  val placedAt: String, // JSON key: "placed_at"
  val paid: Boolean,
  val customer: Customer,
  val items: List<Item>,
)

Option

Serialization annotations

Serialization annotations: on by default. Turn it off for plain data classes with no imports, to annotate for Moshi, Jackson or Gson yourself.

Option

Package

Package: generated by default. Type your module’s package and the declaration at the top follows it.

Where the types come from the library

An integer past Long becomes a JsonPrimitive, whose content property keeps every digit. A list of mixed values is List<JsonElement>, and a key seen only as null is a JsonElement too, each with a comment saying what was in the sample.

Nested classes are named from their keys, in the singular for what a list holds, so the items list is a List<Item>. If the same shape turns up twice, under different keys, it is still one data class. A key that is a Kotlin keyword is kept in backticks, so class stays `class` rather than being renamed. When a type in the document is called List, the standard one is written in full as kotlin.collections.List, so the two never collide.

1

A 20-digit account number, a mixed list, a null and a keyword

{ "account": 12345678901234567890, "codes": [1, "A"], "coupon": null, "class": "A" }
2

JsonPrimitive, JsonElement and `class`

// Generated by myjsoneditor.com for kotlinx.serialization (Kotlin 2.0+).
// Decode with the default Json: explicitNulls = true, so a `T?` with no default is a
// required key that may be null, and `T? = null` is a key that may be absent.

package generated

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive

@Serializable
data class Root(
  val account: JsonPrimitive, // past Long — .content keeps the digits
  val codes: List<JsonElement>, // elements: one of: Long, String
  val coupon: JsonElement, // only null was seen
  val `class`: String,
)

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?

Json.decodeFromString<Root>(text), with your root class in place of Root. Add ignoreUnknownKeys = true to a Json instance to tolerate keys the sample did not have.

Does it work with Moshi or Gson?

The shapes do. Turn off Serialization annotations and add the library’s own, such as @Json(name) for Moshi.

Why are numbers Long rather than Int?

A sample cannot promise a value will stay in Int’s range, so whole numbers use Long. Narrow them where you know better.

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.