前回(ActivityStreamsをKotlinでいい感じに扱いたい(デシリアライズ編) · usbharu - blog)デシリアライズの実装をした際にシリアライズの部分も作ってしまっていたのでDSLのついでに紹介します。
シリアライズ#
シリアライズというかマッピングのほうが正しいような気もする
usbharu/activity-streams-serialization at 00dc4f7939655fb9a1c4276016040821569e4f9a https://github.com/usbharu/activity-streams-serialization/tree/00dc4f7939655fb9a1c4276016040821569e4f9a
(注) CollectionはKotlinのCollectionではなくて独自のCollection
var replies: Collection?
get() = replies()
set(value) {
jsonObject.setOrRemove(Properties.REPLIES, value?.json)
}
fun Object?.replies(objectFactory: ObjectFactory? = this?.objectFactory): Collection? {
if (this == null) {
return null
}
requireNotNull(objectFactory)
val jsonNode = jsonObject.obtain(Properties.REPLIES)?.asArray()?.firstOrNull() ?: return null
require(jsonNode.isObject)
return objectFactory.create(jsonNode) as Collection
}
シリアライズの方もデシリアライズと同じで、SetterでJsonNodeを直接弄っています。
DSL#
テストがすっげぇ~~~面倒なのでDSLを作り始めました。
val object1 = JsonLdBuilder().Note {
attachment {
listOf(
Image {
content("This is what he looks like.")
url("http://example.org/cat.jpeg")
})
}
name("Have you seen my cat?")
}
こんな感じでオブジェクトを組み立てることができます。attachmentのlistOfをなくせるように作ることも考えたんですが、仕組みが複雑になる割にメリット無いのでやめました。
KotlinでDSL作るのって簡単そうに見えて意外とややこしいですよね
実装#
class JsonLdBuilder(var objectFactory: ObjectFactory = DefaultObjectFactory) {
fun Object(block: ObjectBuilder.() -> Unit = {}): Object {
val objectBuilder = ObjectBuilder(objectFactory, this)
objectBuilder.block()
return objectBuilder.Object
}
fun attachment(objectOrLink: ObjectOrLink?): ObjectBuilder {
Object.attachment += objectOrLink ?: return this
return this
}