blog/content/posts/2025-01-20/index.md

100 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
author: usbharu
draft: false
categories:
- 技術
date: 2025-01-20T14:08:58+09:00
tags:
- Kotlin
- ActivityPub
- Kotlin
- ActivityStreams
- ActivityVocabulary
keywords:
- Kotlin
- ActivityPub
- Kotlin
- ActivityStreams
- ActivityVocabulary
title: ActivityStreamsをKotlinでいい感じに扱いたい(DSL編)
relpermalink: posts/2025-01-20/
url: posts/2025-01-20/
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
}
```