5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

D言語Advent Calendar 2024

Day 7

D言語でJSONを扱うときの選択肢としてのmir-ion

Last updated at Posted at 2024-12-07

はじめに

D言語でJSONを扱うときのライブラリとして mir-ion というものが結構良かったので体験記事として共有します。

稚拙の openai-d というライブラリでもサーバー通信周りで要求応答の管理に使っているのですが、静的にSumTypeみたいな型定義ができ、操作の上で安全性も高いところがおすすめポイントです。
以下詳しく説明していきます。

D言語でJSONを扱うときの選択肢

D言語でJSONを扱う場合、真っ先に浮かぶのは標準ライブラリの std.json です。
ライブラリを導入する手間もないので使うのも容易、公式ドキュメントもありますし、日本語Cookbookの解説もあるので第一候補として十分でしょう。

DUBを通じて利用できる他のライブラリも検討すると、DUBパッケージのスコアが高い方から見ておよそ以下の選択肢があります。

  • 標準ライブラリ(std.json)
  • vibe-serialization
    • vibe.dのシリアライズ関連サブパッケージ。vibe-dを参照すれば import vibe.data.json; 等で使える
  • asdf
  • mir-ion
  • jsonizer

他の選択肢は、主に速度などのパフォーマンス改善、記法などを改善して扱いやすくする目的で開発されたものが多いです。
特に asdf は、様々な言語をまたいだJSONシリアライザのパフォーマンスランキングでもかなり上位の部類です(確か数年前は、The Fastest Json Serializer みたいな文言を掲げていたはず…)。今もC++や一部Rustのを除くと3番手ですね。すごい。

mir-ionとは

この中でおすすめしたいと思ったのが、今回触った mir-ion です。
なんで asdf じゃないの?という話をすると、asdfmir-ion は同じ作者で、mir-ion のほうが後発で若干機能豊富、2024年時点ではメンテナンスもこちらがやや活発、という背景があるからです。

なお、mir というのはD言語のライブラリシリーズの名称です。他に mir-alfogithm, mir-blas, mir-lapack, mir-lubeckなどがあります。科学計算に関するものが多いイメージですね。

また -ion とついていますが、これは Amazon Ion というAmazonが開発した階層型シリアライズフォーマットのことです。これが転じて、mir-ion はJSONも扱えるライブラリになっています。(他にもyamlとかmsgpackとかも使える)

mir-ionでJSONを使う

何はともあれ、ざっとサンプルを見てみます。

import mir.ser.json;   // JSONシリアライゼーション用モジュール
import mir.deser.json; // JSONデシリアライゼーション用モジュール
import std.stdio;

// シリアライズ対象の構造体を定義
struct Person {
    string name;
    int age;
}

void main() {
    // Person構造体のインスタンスを作成
    Person original = Person("Alice", 30);

    // 構造体をJSON文字列にシリアライズ
    string jsonString = original.serializeJson();
    writeln("Serialized JSON: ", jsonString);

    // JSON文字列を構造体にデシリアライズ
    Person deserialized = jsonString.deserializeJson!Person();
    writeln("Deserialized Person: ", deserialized);
}

使うモジュールは、mir.ser.jsonmir.deser.json です。
使うのは serializeJsondeserializeJson ですね。これだけ覚えれば使うのはなんとかなります。

属性によるカスタマイズ

どんなライブラリでも細かいことをしようとすると、色々手間がかかります。
しかしそこは我らがD言語、属性(UDA)を追加することで大体なんとかなります。

フィールドに付ける系UDA
// mir-coreからimportするのでパッケージ名に注意
import mir.serde;

struct Example {
    // JSON custom key specification
    // キー名を変える場合
    @serdeKeys("encoding_format")
    string encodingFormat;

    // Optional key specification
    // Nullableとの組み合わせでOptionalを表現
    @serdeOptional
    Nullable!ChatMessageFunctionCall functionCall = null;

    // Exclusion from serialization
    // デフォルト値(null、stringなら空文字も)はシリアライズ時に含めない
    @serdeIgnoreDefault
    string model;
構造体などの型に付ける系UDA
// mir-coreからimportするのでパッケージ名に注意
import mir.serde;

// 無効なキーが含まれる場合、単にそれを除外して扱う
@serdeIgnoreUnexpectedKeys
struct EmbeddingResponse { ... }

他にも色々あるので公式サンプルを見てみてください。

mir-coreで定義された便利機能 Algebraic

mir-ionを支えるコア機能として、 mir.algebraic というモジュールがあります。

これは std.sumtype で出来ることはほぼ同じで、いわゆる代数的データ型、2つの型AとBがあるとき、 A or B が入る、みたいな型が定義できます。

これだけで一本記事が書けそうなので概略を伝えるに留めますが、mir-algorithm では、これを使ってJsonAlgebraic という型が定義されており、動的な部分を極力減らして安全にデータが取り扱えるようになっています。

mir-coreにAlgebraic型があり、mir-algorithmでJsonAlgebraicが定義され、それをmir-ionでシリアライズ/デシリアライズする、という構図なので結構ややこしい)

他の実用例としては、openai-dだと生成AIのAPIを叩くときのストップトークンを指定するところで、未指定、stringで1個指定する、string[]で指定する、という3パターンある箇所があります。
これはAlgebraic型を使って以下のような定義にしました。

nullまたはstringまたはstring[]
import mir.algebraic;

alias StopToken = Algebraic!(typeof(null), string, string[]);

これで以下のようにアクセスする必要があるため、静的に型検査され安全になります。

使い方サンプル
StopToken st = "。";

st.match!(
  (typeof(null) _) {},
  (string token) {},
  (string[] tokens) {}
  );

JSONで型の重ね合わせ表現みたいなものが最近多いですが、AlgebraicでA or Bという表現をしておけばある程度適切に分岐してもらえます。
デシリアライズのほうは判定用のキーを指定するなど調整も必要ですが、それは公式サンプルなどを探してみてください。

おわりに

以上、mir-ionを使ったJSONの取り扱いに関する宣伝記事でした。

普段は std.json で困らないと思いますが、外部APIとのやり取り、複雑な重ね合わせのようなデータ表現と静的な構造体などへのマッピングが欲しいな、と思ったら候補になると思います。

というわけで、たまのライブラリ紹介記事でした。
みなさんも使ってるライブラリでおすすめがあれば紹介してください!!!

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?