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) } // <-- JsonNode
import 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 string
The 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 Byte
You 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"
}