左側に Scala を貼り付けて 「変換」をクリック — XML に変換しますScala コードを貼り付けてください

このツールでできること

Scala の case class に対応する XML ペイロードが必要になったこと、ありますよね — Akka HTTP のフィクスチャ用、Play Framework の設定用、レガシーな SOAP 連携、あるいはテスト用。そのたびに手で XML を書くのはしんどい作業です。ここに Scala を貼り付ければ、きちんとした XML がすぐに返ってきます。単一の case class でも、値の入った val でも、入れ子の型を含むファイル全体でも、すべてのフィールドを保ったまま通り抜けます。

このコンバーターは、Scala が実際に XML に落ちるときの形をちゃんと理解しています。末尾に接尾辞のついた BigDecimal リテラルはそのまま数値テキストとして出力され、None を保持する Option[String] フィールドは黙って消えるのではなく空要素にマッピングされます。List[T]Seq[T] はコンテナ要素になり、要素の型名を持つ子を 1 件ずつ持ちます。Map[K,V]<Entry><Key/><Value/></Entry> のペアになります。これはモデルをラウンドトリップさせたときに scala-xmljackson-module-scala が吐き出す形と同じです。

入れ子の case class は入れ子の要素に展開され、コンパニオンオブジェクトの定数は無視されます。sealed trait の階層では、具体サブタイプの名前がそのまま要素タグとして残ります。複数のクラスをまとめて貼り付けても大丈夫です — 関係性は維持されるので、OrderList[OrderItem]ShippingAddress が含まれていれば、3 つとも一緒に返ってきます。データとして扱われるものと振る舞いとして扱われるものの違いは、公式の case class ツアーで復習できます。

使い方

3 ステップ。5 行の case class を貼り付けても、モデルファイル丸ごと貼り付けても流れは同じです。

1

Scala を貼り付ける(もしくはサンプルを読み込む)

コードをそのまま左側のエディタに落としてください。単一の case class、値の入った val インスタンス複数のクラスsealed trait の階層 — どれでもパーサーは問題なく扱えます。まず現実的な例を見たい場合は サンプルを読み込む を押してください。

import を外したり、package 宣言を消したり、Scala 構文を整えたりする必要はありません。IntelliJ や Metals で見ているそのままの形で OK です。貼り付けるだけ。

2

変換を押す

緑色の 変換 ボタンをクリックします。ツールが case class をパースし、値の入ったインスタンスを走査して、一度のパスで XML を組み立てます。処理中は短いローディング表示が出ます。

3

XML をコピー

右側のパネルに、インデント済みの整形された XML が表示されます。標準準拠のどんなパーサーでも受け付けてくれる形です。そのまま Akka HTTP のテスト、Play の XML ボディ、SBT のリソースファイル、必要な場所にコピーしてください。

実際にどこで役立つか

Akka HTTP と Play のフィクスチャ

Akka HTTP や Play で受け取る XML リクエストの case class があり、テストや curl コマンド用に現実的なボディが欲しい。クラスを貼り付けて XML を受け取り、そのまま spec に落とし込めます。

レガシーシステム向けの XML 設定

30 フィールドの設定用 case class が、Mule、WebLogic、IBM MQ、社内ツールなど、今も XML を欲しがる古いプラットフォーム向けの編集可能な XML テンプレートになります。

コードと一致するドキュメント

README、ScalaDoc、Confluence 用の XML サンプルを、本物の case class から直接生成できます。ドキュメントがモデルからズレません。

SOAP や scala-xml 向けのテストデータ

ユニットテストで使っている値入りインスタンスを、結合テスト・WireMock のスタブ・まだ SOAP を話すシステム向けの XML シードファイルに変換できます。

よくある質問

複数の case class を一度に貼り付けられますか?

はい — ファイルごと貼り付けて大丈夫です。トップレベルの case class はそれぞれ、入れ子の型を展開した形で返ってきて、コンパニオンオブジェクトのヘルパーは無視されます。OrderList[OrderItem] が入っていれば、両方とも適切な入れ子で出力されます。

Option、None、デフォルト値はどう扱われますか?

Some("x") を保持する Option[String] は、テキストを中に持つ普通の要素になります。None は空要素になるので、XML の形が崩れません — 黙って捨てられることはありません。case class のフィールドに設定されたデフォルト値は、インスタンスにそのフィールドが無いときに使われます。

BigDecimal、Instant、UUID、ちょっと癖のある数値型は?

BigDecimal は接尾辞を落として、そのまま数値テキストになります。java.time.InstantLocalDateLocalDateTime は ISO-8601 文字列に、UUID は標準の 8-4-4-4-12 の 16 進形式のまま残ります。プリミティブのラッパー(IntLongDoubleBoolean)はそのままテキストとして出力されます — jackson-module-scala がデフォルトで吐き出すのと同じ形です。

List、Seq、Set、Map は全部同じ扱いですか?

ほぼ同じです。List[T]Seq[T]Vector[T]Set[T] はいずれもコンテナ要素になり、要素の型名を持つ子を 1 件ずつ持ちます — つまり Items: List[OrderItem]<Items><OrderItem/><OrderItem/></Items> になります。Map[K,V]<Entry><Key/><Value/></Entry> のコンテナになります。

コードは保存されますか?

変換のためにバックエンドには送信されますが、保存はしません — ペイロードはログにも残しません。本当に機密性の高い Scala なら、他のオンラインツールと同じく、貼り付ける前にざっと目を通してください。

暗黙の型変換、型クラス、マクロが含まれているとどうなりますか?

暗黙の変換やマクロ生成コードは、それ自体が XML フィールドを生み出すわけではありません — 宣言された case class のメンバーから組み立てます。つまり implicit val format@JsonCodec アノテーションは事実上無視され、素のフィールド形状が返ってきます。構文エラーがあるなら、まず明らかなものを直してください。

合わせて使えるツール

Scala から XML はパズルの 1 ピース。こんなツールとも相性がいいです: