Kotlin native DSL for Jackson Object Mapper to describe JSON in code.
The library requires at least java 8.
The client can be pulled into gradle or maven by using jitpack.
Gradle
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.cmdjulian:jdsl:{VERSION}'
}Gradle Kts
repositories {
maven(url = "https://jitpack.io")
}
dependencies {
implementation("com.github.cmdjulian:jdsl:{VERSION}")
}Maven
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
...
<dependencies>
<dependency>
<groupId>com.github.cmdjulian</groupId>
<artifactId>jdsl</artifactId>
<version>{VERSION}</version>
</dependency>
</dependencies>
</project>// empty array '[ ]'
arr
arr()
arr { }
// results in '[1, 2, 3]'
arr[1, 2, 3]
arr {
add(1)
add(2)
add(3)
}// empty object '{ }'
obj { }
// object with keys '{ "foo": "bar" }'
obj {
"foo" `=` "bar"
}Literals are not required to be used in the dsl. However, if you need an instance of a JsonNode, this can be a quick
way to achieve that.
You can also use it top convert any pojo to json.
json(5) // <-- ValueNode
json { 5 } // <-- JsonNode
json { Pair(1, 2) } // <-- JsonNodeimport java.time.OffsetDateTime
obj {
"foo" `=` "bar"
"integer" `=` 1337
"boolean" `=` true
"nullable" `=` `null`
"float" `=` 69.0
"time" `=` OffsetDateTime.now()
"enum" `=` Sort.ASC
"nested-object" `=` obj { "fizz" `=` "buzz" }
"array-of-numbers" `=` arr[1, 2, 3]
"array-of-objects" `=` arr[
obj { "name" `=` "tony stark" },
obj { "name" `=` "steve rogers" }
]
"empty-arr" `=` arr
"pojo" `=` json { Pair("airbus", "boeing") }
}
this results in the following JSON:
{
"foo": "bar",
"integer": 1337,
"boolean": true,
"nullable": null,
"time": "2022-10-28T20:49:03.121449+02:00",
"enum": "ASC",
"float": 1337.0,
"nested-object": {
"fizz": "buzz"
},
"array-of-numbers": [
1,
2,
3
],
"array-of-objects": [
{
"name": "tony stark"
},
{
"name": "steve rogers"
}
],
"empty-arr": [],
"pojo": {
"first": "airbus",
"second": "boeing"
}
}As default, the obj and arr functions return Jackson's ObjectNode and ArrayNode, however, if you want for
instance a pretty printed String or Byte, you can supply a processor.
The following code for instance returns string:
obj(Transformers.String) { "fizz" `=` "buzz" } // <-- return type is string
arr(Transformers.Byte) { add(1) } // <-- return type is byte
json(Transformers.String) { 5 } // <-- return type is stringThe library includes transformers for String and Byte. However, if you for instance want to convert json to CSV or
some other format / object, you can provide your own transformer by implementing the Transformer interface.
As arr[] doesn't support transformer, you can wrap it inside a json block, which in turn does support transformer:
json(Transformers.Byte) { arr[1, 2, 3] } // <-- return type is ByteYou can even use the included ObjectMapper Transformer to get arbitrary objects from the json
via Jackson ObjectMapper:
data class FizzBuzz(val fizz: String)
val json: FizzBuzz = obj(transformer = Transformers.ObjectMapper()) {
"fizz" `=` "buzz"
}Under the hood, an ObjectMapper is used to convert the JsonNode into a class. As default, the modules kotlinModule
, Jdk8Module and JavaTimeModule are registered. You can also customize the used mapper:
val mapper = jsonMapper { }
obj(transformer = Transformers.ObjectMapper(mapper)) {
"fizz" `=` "buzz"
}You could also create named objects to simplify the mapping for a specific type:
data class FizzBuzz(val fizz: String)
object FizzBuzzTransformer : Transformers.ObjectMapper<FizzBuzz>(FizzBuzz::class.java)
val json = obj(transformer = FizzBuzzTransformer) {
"fizz" `=` "buzz"
}