Skip to content
ZeroServer.tools

JSON to Kotlin Data Class

Generate Kotlin data classes for kotlinx.serialization from a JSON sample, with @Serializable and @SerialName. Every value is typed, and a key that some objects lack or hold as null is nullable.

Nullable properties
or drop a file here

About JSON to Kotlin

The objects in the JSON become Kotlin data classes for kotlinx.serialization. Each class is @Serializable, so Json.decodeFromString reads the JSON into it and Json.encodeToString writes it back, and a property whose name is not its key, such as createdAt for created_at, has a @SerialName with the key.

Every value at a place counts, not just the first. A number is an Int, a Long once one is beyond 32 bits, and a Double when one is written with a fraction or an exponent, as 10.0 and 1.5e3 are, since kotlinx.serialization reads neither as an Int. The objects at one place, such as the items of a list, make one class, with the keys in the order first seen. A key that is null in some objects is nullable, as in String?. One that some objects lack is nullable with a default of null, as in val coupon: String? = null, since kotlinx.serialization throws on an object that lacks a key whose property has no default.

kotlinx.serialization has no serializer for Any, so a key that holds two kinds of value, such as a string and a number, or only null, is a JsonElement, which holds any JSON as it is written, and objects that are always empty are a JsonObject. A note says why, as one does for each number a Double rounds and each null that is not written back.

Properties are lowerCamelCase, so user_id and userID both read as userId, and the second gets a number: userId2. A keyword such as class or val has Value added, and a class name that would hide a Kotlin type, such as List or Result, has Model added.

An object with so many keys that the JVM would not load its class, such as 246 that hold an Int or 125 that hold a Double, becomes a Map<String, T>, with a note. When the JSON is an array of objects, the class describes them, and a note gives the type that reads the whole array. Choose Every property to make every property nullable, with a default of null, for an API that can leave any key out. Everything runs in your browser.

For Dart, see JSON to Dart Class. For Java, try JSON to Java Class, and for Swift, JSON to Swift Struct.

Built and maintained by Meet Shah · Last updated

What this tool is used for

  • Generating kotlinx.serialization models from an API response for an Android or Ktor app.
  • Getting the @SerialName right for keys in snake_case, or with characters a Kotlin name cannot hold.
  • Producing a starting model for an endpoint with no published schema.
  • Creating data classes for a test fixture that match production shapes.
  • Seeing how a payload's nesting maps onto nested Kotlin classes.

Frequently Asked Questions

How do JSON types map to Kotlin?
Strings are String, booleans Boolean, objects a data class and arrays a List. A number is an Int, a Long once a sample is beyond 32 bits, and a Double when a sample has a fraction or an exponent, as 10.0 and 1.5e3 do, or is an integer beyond a Long. A key null in some samples is nullable, as in String?.
Why is a property a JsonElement and not Any?
kotlinx.serialization has no serializer for Any, so it cannot read JSON into an Any property. A JsonElement holds any JSON as it is written, so a key with two kinds of value, such as a string and a number, or only null, is one, and a note says why. Objects that are always empty are a JsonObject.
When is @SerialName written?
Only where a property's name is not its key, as createdAt is for created_at, classValue for class and field2Fa for 2fa. kotlinx.serialization reads and writes a property under its own name unless a @SerialName gives another, so each key is kept exactly as the JSON has it, $ref and it's included.
Why does a key some objects lack get = null?
kotlinx.serialization throws a MissingFieldException on an object that lacks a key whose property has no default, so such a key is nullable with a default of null, as in val coupon: String? = null. A property that holds its default is left out when written back, so a null the JSON has there is not written back.
Why is an object sometimes a Map?
kotlinx.serialization gives a class a constructor with a parameter per property and a few more, and JVM method parameters fill at most 255 slots, two for a Long or Double that is not nullable. Past that the class compiles but does not load: 245 Int properties load, 246 do not. Such objects are a Map<String, T>.
Should every property be nullable?
A sample shows only some of the keys an API can send as null or leave out: here a key that is null is nullable, and one that some objects lack also gets a default of null. The API contract says which others are. Every property makes them all nullable, each with a default of null, so a response can leave any key out.

Common errors and gotchas

  • Trusting the nullability one sample shows: a key present in every object of the sample can still be left out of a real response, and kotlinx.serialization then throws a MissingFieldException. Choose Every property when the API contract does not say.
  • Generating from a sample where a decimal field happens to hold a whole number, such as a price of 12: the property is typed Int, and kotlinx.serialization then refuses 12.5. Use a sample with a fraction, or write 12.0.
  • Renaming a property without a @SerialName: kotlinx.serialization reads and writes each property under its own name, so a createdAt with no annotation names no key the JSON has, and reading created_at into it throws.
  • Naming a class after a type Kotlin already has, such as List, Map or Result: the class hides Kotlin's type in its package, which is why a key named list gives a class ListModel here.
  • Sending an ID beyond the range of a Long as a JSON number: its property is a Double, which holds integers exactly only up to 2^53, so the ID is rounded. Send such an ID as a string.
  • Expecting an unknown key to be skipped: kotlinx.serialization's default Json throws on a key the class has no property for, so a response that gains a field breaks the read. Build the Json with ignoreUnknownKeys = true when the API can add fields.

Related Converters tools

Private & free — this tool runs entirely in your browser.

IndieKit — Ship your Next.js startup in days.affiliate