--- author: usbharu draft: true categories: - 技術 date: 2025-01-12T14:08:58+09:00 tags: - Kotlin - ActivityPub - Kotlin - ActivityStreams - ActivityVocabulary keywords: - Kotlin - ActivityPub - Kotlin - ActivityStreams - ActivityVocabulary title: ActivityStreamsをKotlinでいい感じに扱いたい(DSL編) relpermalink: posts/2025-01-12/ url: posts/2025-01-12/ decription: ActivityStreamsをKotlinでいい感じに扱いたい(シリアライズ・DSL編) --- 前回([ActivityStreamsをKotlinでいい感じに扱いたい(デシリアライズ編) · usbharu - blog](https://blog.usbharu.dev/posts/2025-01-12/))デシリアライズの実装をした際にシリアライズの部分も作ってしまっていたのでDSLのついでに紹介します。 ## シリアライズ シリアライズというかマッピングのほうが正しいような気もする usbharu/activity-streams-serialization at 00dc4f7939655fb9a1c4276016040821569e4f9a https://github.com/usbharu/activity-streams-serialization/tree/00dc4f7939655fb9a1c4276016040821569e4f9a (注) CollectionはKotlinのCollectionではなくて独自のCollection ```kotlin 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を作り始めました。 [DSL](https://github.com/usbharu/activity-streams-serialization/blob/00dc4f7939655fb9a1c4276016040821569e4f9a/src/test/kotlin/dev/usbharu/hideout/activitystreams/core/ObjectTest.kt#L77-L86) ``` 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作るのって簡単そうに見えて意外とややこしいですよね ### 実装 [オブジェクトの作成](https://github.com/usbharu/activity-streams-serialization/blob/00dc4f7939655fb9a1c4276016040821569e4f9a/src/main/kotlin/dev/usbharu/hideout/activitystreams/dsl/JsonLd.kt) ```kotlin class JsonLdBuilder(var objectFactory: ObjectFactory = DefaultObjectFactory) { fun Object(block: ObjectBuilder.() -> Unit = {}): Object { val objectBuilder = ObjectBuilder(objectFactory, this) objectBuilder.block() return objectBuilder.Object } ``` [プロパティの設定](https://github.com/usbharu/activity-streams-serialization/blob/00dc4f7939655fb9a1c4276016040821569e4f9a/src/main/kotlin/dev/usbharu/hideout/activitystreams/dsl/ObjectBuilder.kt) ```kotlin fun attachment(objectOrLink: ObjectOrLink?): ObjectBuilder { Object.attachment += objectOrLink ?: return this return this } ```