Kotlin multiplatform JSON serialization library with JavaScript-specific dynamic object conversion capabilities
—
Programmatic JSON tree manipulation with a rich hierarchy of JsonElement types for building and accessing JSON structures. The JsonElement API provides a type-safe way to work with JSON data at the tree level.
The base class and hierarchy for representing JSON values as a tree structure.
/**
* Represents a JSON element - base class for all JSON values
*/
sealed class JsonElement
/**
* Represents JSON primitive values (strings, numbers, booleans, null)
*/
abstract class JsonPrimitive : JsonElement {
/**
* Raw string content of the primitive value
*/
abstract val content: String
/**
* True if this primitive represents a JSON string value
*/
val isString: Boolean
}
/**
* Represents JSON objects with key-value pairs
*/
class JsonObject(val content: Map<String, JsonElement>) : JsonElement, Map<String, JsonElement>
/**
* Represents JSON arrays
*/
class JsonArray(val content: List<JsonElement>) : JsonElement, List<JsonElement>
/**
* Represents JSON null value
*/
object JsonNull : JsonPrimitive()Convenience extension properties for type-safe conversion between JsonElement types.
/**
* Convenience method to get current element as JsonPrimitive
* @throws IllegalArgumentException if current element is not a JsonPrimitive
*/
val JsonElement.jsonPrimitive: JsonPrimitive
/**
* Convenience method to get current element as JsonObject
* @throws IllegalArgumentException if current element is not a JsonObject
*/
val JsonElement.jsonObject: JsonObject
/**
* Convenience method to get current element as JsonArray
* @throws IllegalArgumentException if current element is not a JsonArray
*/
val JsonElement.jsonArray: JsonArray
/**
* Convenience method to get current element as JsonNull
* @throws IllegalArgumentException if current element is not a JsonNull
*/
val JsonElement.jsonNull: JsonNullUsage Examples:
val json = Json.Default
val jsonString = """{"users": [{"name": "Alice", "age": 25}, {"name": "Bob", "age": null}]}"""
val element = json.parseToJsonElement(jsonString)
// Access nested elements with type safety
val rootObject = element.jsonObject
val usersArray = rootObject["users"]!!.jsonArray
val firstUser = usersArray[0].jsonObject
val userName = firstUser["name"]!!.jsonPrimitive.content
val userAge = firstUser["age"]!!.jsonPrimitive.int
println("User: $userName, Age: $userAge") // User: Alice, Age: 25
// Handle null values
val secondUserAge = usersArray[1].jsonObject["age"]
if (secondUserAge is JsonNull) {
println("Second user age is null")
}Create JsonPrimitive instances from various Kotlin types.
/**
* Creates JsonPrimitive from Boolean value
*/
fun JsonPrimitive(value: Boolean?): JsonPrimitive
/**
* Creates JsonPrimitive from Number value
*/
fun JsonPrimitive(value: Number?): JsonPrimitive
/**
* Creates JsonPrimitive from String value
*/
fun JsonPrimitive(value: String?): JsonPrimitive
/**
* Creates JsonPrimitive from unsigned integer types
*/
@ExperimentalSerializationApi
fun JsonPrimitive(value: UByte): JsonPrimitive
@ExperimentalSerializationApi
fun JsonPrimitive(value: UShort): JsonPrimitive
@ExperimentalSerializationApi
fun JsonPrimitive(value: UInt): JsonPrimitive
@ExperimentalSerializationApi
fun JsonPrimitive(value: ULong): JsonPrimitive
/**
* Creates unquoted JSON literal (experimental)
* Be aware that it is possible to create invalid JSON using this function
* @throws JsonEncodingException if value == "null"
*/
@ExperimentalSerializationApi
fun JsonUnquotedLiteral(value: String?): JsonPrimitiveUsage Examples:
// Create primitive values
val stringPrimitive = JsonPrimitive("hello")
val numberPrimitive = JsonPrimitive(42)
val boolPrimitive = JsonPrimitive(true)
val nullPrimitive = JsonPrimitive(null as String?) // Creates JsonNull
// Unsigned integer support
val uintPrimitive = JsonPrimitive(42u)
val ulongPrimitive = JsonPrimitive(9223372036854775808UL)
// Check primitive types
println(stringPrimitive.isString) // true
println(numberPrimitive.isString) // false
println(stringPrimitive.content) // "hello"
println(numberPrimitive.content) // "42"
// Unquoted literals for precise numbers
val preciseNumber = JsonUnquotedLiteral("123.456789012345678901234567890")
val largeInteger = JsonUnquotedLiteral("12345678901234567890123456789")Type-safe accessors for extracting values from JsonPrimitive instances.
/**
* Content as string, or null if this is JsonNull
*/
val JsonPrimitive.contentOrNull: String?
/**
* Returns content as Int
* @throws NumberFormatException if not a valid representation
*/
val JsonPrimitive.int: Int
/**
* Returns content as Int or null if invalid
*/
val JsonPrimitive.intOrNull: Int?
/**
* Returns content as Long
* @throws NumberFormatException if not a valid representation
*/
val JsonPrimitive.long: Long
/**
* Returns content as Long or null if invalid
*/
val JsonPrimitive.longOrNull: Long?
/**
* Returns content as Double
* @throws NumberFormatException if not a valid representation
*/
val JsonPrimitive.double: Double
/**
* Returns content as Double or null if invalid
*/
val JsonPrimitive.doubleOrNull: Double?
/**
* Returns content as Float
* @throws NumberFormatException if not a valid representation
*/
val JsonPrimitive.float: Float
/**
* Returns content as Float or null if invalid
*/
val JsonPrimitive.floatOrNull: Float?
/**
* Returns content as Boolean
* @throws IllegalStateException if not a valid boolean representation
*/
val JsonPrimitive.boolean: Boolean
/**
* Returns content as Boolean or null if invalid
*/
val JsonPrimitive.booleanOrNull: Boolean?Usage Examples:
val json = Json.Default
val element = json.parseToJsonElement("""
{
"name": "Alice",
"age": 25,
"height": 5.6,
"isActive": true,
"score": null
}
""")
val obj = element.jsonObject
// Safe type conversions
val name = obj["name"]!!.jsonPrimitive.content // "Alice"
val age = obj["age"]!!.jsonPrimitive.int // 25
val height = obj["height"]!!.jsonPrimitive.double // 5.6
val isActive = obj["isActive"]!!.jsonPrimitive.boolean // true
// Handle null values
val score = obj["score"]!!.jsonPrimitive.contentOrNull // null
// Safe conversions with null fallback
val invalidAge = JsonPrimitive("not-a-number").intOrNull // null
val validAge = JsonPrimitive("30").intOrNull // 30
// Check if primitive contains actual content
val nullPrimitive = JsonNull
println(nullPrimitive.contentOrNull) // null
println(nullPrimitive.content) // "null"/**
* JsonPrimitive value accessors with exception-throwing variants
*/
val JsonPrimitive.int: Int
val JsonPrimitive.intOrNull: Int?
val JsonPrimitive.long: Long
val JsonPrimitive.longOrNull: Long?
val JsonPrimitive.double: Double
val JsonPrimitive.doubleOrNull: Double?
val JsonPrimitive.float: Float
val JsonPrimitive.floatOrNull: Float?
val JsonPrimitive.boolean: Boolean
val JsonPrimitive.booleanOrNull: Boolean?Usage Examples:
val numberElement = JsonPrimitive(123)
val boolElement = JsonPrimitive(true)
val stringElement = JsonPrimitive("456")
// Safe extraction
val intValue = numberElement.int // 123
val boolValue = boolElement.boolean // true
val intFromString = stringElement.int // 456 (parsed from string)
// Null-safe extraction
val safeInt = numberElement.intOrNull // 123
val safeFloat = boolElement.floatOrNull // null (can't convert boolean to float)
// Working with JsonNull
val nullElement = JsonNull
val nullInt = nullElement.intOrNull // null
val nullContent = nullElement.contentOrNull // nullJsonObject implements Map interface providing standard map operations for JSON objects.
/**
* JsonObject constructor and map operations
*/
class JsonObject(val content: Map<String, JsonElement>) : JsonElement, Map<String, JsonElement> {
// Inherits all Map operations:
// get(key), containsKey(key), isEmpty(), size, keys, values, entries, etc.
}Usage Examples:
// Create JsonObject
val jsonObject = JsonObject(mapOf(
"name" to JsonPrimitive("Alice"),
"age" to JsonPrimitive(30),
"isActive" to JsonPrimitive(true)
))
// Access properties
val name = jsonObject["name"]?.jsonPrimitive?.content // "Alice"
val age = jsonObject["age"]?.jsonPrimitive?.int // 30
val active = jsonObject["isActive"]?.jsonPrimitive?.boolean // true
// Check existence
if ("email" in jsonObject) {
val email = jsonObject["email"]?.jsonPrimitive?.content
}
// Iterate over properties
for ((key, value) in jsonObject) {
println("$key: $value")
}
// Get all keys and values
val keys = jsonObject.keys // Set<String>
val values = jsonObject.values // Collection<JsonElement>
val entries = jsonObject.entries // Set<Map.Entry<String, JsonElement>>JsonArray implements List interface providing standard list operations for JSON arrays.
/**
* JsonArray constructor and list operations
*/
class JsonArray(val content: List<JsonElement>) : JsonElement, List<JsonElement> {
// Inherits all List operations:
// get(index), size, isEmpty(), iterator(), contains(element), etc.
}Usage Examples:
// Create JsonArray
val jsonArray = JsonArray(listOf(
JsonPrimitive("apple"),
JsonPrimitive("banana"),
JsonPrimitive("cherry")
))
// Access elements
val firstItem = jsonArray[0].jsonPrimitive.content // "apple"
val secondItem = jsonArray[1].jsonPrimitive.content // "banana"
// Check size and bounds
val size = jsonArray.size // 3
val isEmpty = jsonArray.isEmpty() // false
// Iterate over elements
for (element in jsonArray) {
val value = element.jsonPrimitive.content
println(value)
}
// Convert to regular list
val stringList = jsonArray.map { it.jsonPrimitive.content }
// Result: ["apple", "banana", "cherry"]
// Check if element exists
val containsApple = jsonArray.any {
it.jsonPrimitive.content == "apple"
} // trueSafe type checking and casting utilities for JsonElement instances.
/**
* Type checking extension properties
*/
val JsonElement.jsonPrimitive: JsonPrimitive
val JsonElement.jsonObject: JsonObject
val JsonElement.jsonArray: JsonArray
val JsonElement.jsonNull: JsonNullUsage Examples:
fun processJsonElement(element: JsonElement) {
when {
element is JsonPrimitive -> {
println("Primitive: ${element.content}")
// Safe casting
val primitive = element.jsonPrimitive
if (primitive.isString) {
println("String value: ${primitive.content}")
} else {
val numValue = primitive.doubleOrNull
println("Numeric value: $numValue")
}
}
element is JsonObject -> {
println("Object with ${element.size} properties")
val obj = element.jsonObject
obj.forEach { (key, value) ->
println(" $key: $value")
}
}
element is JsonArray -> {
println("Array with ${element.size} elements")
val array = element.jsonArray
array.forEachIndexed { index, value ->
println(" [$index]: $value")
}
}
element is JsonNull -> {
println("Null value")
}
}
}
// Safe casting example
fun extractStringValue(element: JsonElement): String? {
return (element as? JsonPrimitive)?.takeIf { it.isString }?.content
}
fun extractObjectProperty(element: JsonElement, key: String): JsonElement? {
return (element as? JsonObject)?.get(key)
}Working with nested JSON structures using the element API.
Usage Examples:
// Complex nested structure
val complexJson = JsonObject(mapOf(
"user" to JsonObject(mapOf(
"id" to JsonPrimitive(123),
"profile" to JsonObject(mapOf(
"name" to JsonPrimitive("Alice"),
"emails" to JsonArray(listOf(
JsonPrimitive("alice@work.com"),
JsonPrimitive("alice@personal.com")
))
))
)),
"settings" to JsonObject(mapOf(
"theme" to JsonPrimitive("dark"),
"notifications" to JsonPrimitive(true)
))
))
// Navigate nested structure
val userId = complexJson["user"]
?.jsonObject?.get("id")
?.jsonPrimitive?.int // 123
val userName = complexJson["user"]
?.jsonObject?.get("profile")
?.jsonObject?.get("name")
?.jsonPrimitive?.content // "Alice"
val firstEmail = complexJson["user"]
?.jsonObject?.get("profile")
?.jsonObject?.get("emails")
?.jsonArray?.get(0)
?.jsonPrimitive?.content // "alice@work.com"
val theme = complexJson["settings"]
?.jsonObject?.get("theme")
?.jsonPrimitive?.content // "dark"
// Safe navigation with null checks
fun extractUserName(json: JsonElement): String? {
return (json as? JsonObject)
?.get("user")?.let { it as? JsonObject }
?.get("profile")?.let { it as? JsonObject }
?.get("name")?.let { it as? JsonPrimitive }
?.content
}Build JsonElement structures programmatically for dynamic JSON generation.
Usage Examples:
// Build a user object programmatically
fun createUserJson(id: Int, name: String, emails: List<String>): JsonObject {
return JsonObject(mapOf(
"id" to JsonPrimitive(id),
"name" to JsonPrimitive(name),
"emails" to JsonArray(emails.map { JsonPrimitive(it) }),
"isActive" to JsonPrimitive(true),
"lastLogin" to JsonNull
))
}
val userJson = createUserJson(
id = 456,
name = "Bob",
emails = listOf("bob@example.com", "bob2@example.com")
)
// Convert to string for transmission
val json = Json.Default
val jsonString = json.encodeToString(JsonElement.serializer(), userJson)
// Build conditional structure
fun createResponseJson(success: Boolean, data: Any? = null, error: String? = null): JsonObject {
val elements = mutableMapOf<String, JsonElement>(
"success" to JsonPrimitive(success),
"timestamp" to JsonPrimitive(System.currentTimeMillis())
)
if (success && data != null) {
elements["data"] = json.encodeToJsonElement(data)
}
if (!success && error != null) {
elements["error"] = JsonPrimitive(error)
}
return JsonObject(elements)
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-json-js