This is an experimental JSON5 library for Kotlin/JVM and Kotlin/Native. It makes use of the kotlinx.serialization framework to serialize object hierarchies into standard-compliant JSON5 text and vice versa.
- Compliance with v1.0.0 of the JSON5 specification
- Support for polymorphic types and configurable class discriminators
- Concise error messages for deserialization errors
- Support for the serialization of comments for class properties
- Rejection of duplicate keys during deserialization
json5k is available on Maven Central:
plugins {
kotlin("jvm") version "1.8.10"
kotlin("plugin.serialization") version "1.8.10"
}
repositories {
mavenCentral()
}
dependencies {
implementation("io.github.xn32:json5k:0.3.0")
}
Official versions are published for the following targets:
- Java Virtual Machine:
jvm
- x86-64 platforms:
linuxX64
,macosX64
,iosX64
,mingwX64
- Apple Silicon platforms:
macosArm64
,iosArm64
,iosSimulatorArm64
Snapshot versions of the main
branch are available from here.
import io.github.xn32.json5k.Json5
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
// Serialization:
Json5.encodeToString(5142) // 5142
Json5.encodeToString(listOf(4.5, 1.5e2, 1.2e15)) // [4.5,150.0,1.2E15]
Json5.encodeToString(mapOf("a" to 10, "b" to 20)) // {a:10,b:20}
Json5.encodeToString(Double.NEGATIVE_INFINITY) // -Infinity
Json5.encodeToString<Int?>(null) // null
// Deserialization:
Json5.decodeFromString<Int?>("113") // 113
Json5.decodeFromString<List<Double>>("[1.2, .4]") // [1.2, 0.4]
Json5.decodeFromString<Map<String, Int>>("{ a: 10, 'b': 20, }") // {a=10, b=20}
Json5.decodeFromString<Double>("+Infinity") // Infinity
Json5.decodeFromString<Int?>("null") // null
// Deserialization errors:
Json5.decodeFromString<Byte>("190")
// UnexpectedValueError: signed integer in range [-128..127] expected at position 1:1
Json5.decodeFromString<List<Double>>("[ 1.0,,")
// CharError: unexpected character ',' at position 1:7
import io.github.xn32.json5k.Json5
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@Serializable
data class Person(val name: String, val age: UInt? = null)
// Serialization:
Json5.encodeToString(Person("John", 31u)) // {name:"John",age:31}
Json5.encodeToString(Person("Jane")) // {name:"Jane"}
// Deserialization:
Json5.decodeFromString<Person>("{ name: 'Carl' }") // Person(name=Carl, age=null)
Json5.decodeFromString<Person>("{ name: 'Carl', age: 42 }") // Person(name=Carl, age=42)
// Deserialization errors:
Json5.decodeFromString<Person>("{ name: 'Carl', age: 42, age: 10 }")
// DuplicateKeyError: duplicate key 'age' at position 1:26
import io.github.xn32.json5k.Json5
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@Serializable
data class IntWrapper(@SerialName("integer") val int: Int)
// Serialization:
Json5.encodeToString(IntWrapper(10)) // {integer:10}
// Deserialization:
Json5.decodeFromString<IntWrapper>("{ integer: 10 }") // IntWrapper(int=10)
// Deserialization errors:
Json5.decodeFromString<IntWrapper>("{ int: 10 }")
// UnknownKeyError: unknown key 'int' at position 1:3
import io.github.xn32.json5k.ClassDiscriminator
import io.github.xn32.json5k.Json5
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@Serializable
@ClassDiscriminator("mode")
sealed interface Producer
@Serializable
@SerialName("numbers")
data class NumberProducer(val init: UInt) : Producer
// Serialization:
Json5.encodeToString<Producer>(NumberProducer(10u)) // {mode:"numbers",init:10}
// Deserialization:
Json5.decodeFromString<Producer>("{ init: 0, mode: 'numbers' }") // NumberProducer(init=0)
// Deserialization errors:
Json5.decodeFromString<Producer>("{ init: 0 }")
// MissingFieldError: missing field 'mode' in object at position 1:1
import io.github.xn32.json5k.Json5
import io.github.xn32.json5k.SerialComment
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
@Serializable
data class Person(
val name: String,
val age: UInt? = null
)
@Serializable
data class Event(
@SerialComment("First day of the event")
val date: String,
@SerialComment("Registered attendees")
val attendees: List<Person>
)
val json5 = Json5 {
prettyPrint = true
}
println(
json5.encodeToString(
Event("2022-10-04", listOf(Person("Emma", 31u)))
)
)
Running this code will produce the following output:
{
// First day of the event
date: "2022-10-04",
// Registered attendees
attendees: [
{
name: "Emma",
age: 31
}
]
}
Control generated JSON5 output as follows:
import io.github.xn32.json5k.Json5
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
val json5 = Json5 {
prettyPrint = true
indentationWidth = 2
useSingleQuotes = true
quoteMemberNames = true
encodeDefaults = true
}
@Serializable
data class Person(val name: String, val age: UInt? = null)
println(json5.encodeToString(Person("Oliver")))
This will result in the following output:
{
'name': 'Oliver',
'age': null
}
See the unit tests for serialization and deserialization for more examples.