---
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
    }
```