入力(.proto スキーマ)

出力(Kotlin)

このツールでできること

Protocol Buffers スキーマがあって — バックエンドチームから渡されたものかもしれないし、サードパーティ API の契約かもしれない — それに対応する型付きの形が必要な Kotlin コードベースがある。Android アプリが gRPC バックエンドを呼ぶケース、あるいはサーバーサイド Kotlin が JSON エンコードの Protobuf メッセージをパースするケース。data class の形だけで済むのに grpc-kotlin のフル codegen パイプラインを組むのはやり過ぎ — 貼り付けて、コピーして、配置するだけで済みます。

型マッピングは Kotlin のイディオムに従います: stringStringboolBooleanbytesByteArrayint32/sint32/fixed32Intint64/sint64/fixed64LongdoubleDoublefloatFloatrepeated T はデフォルト emptyList() 付きの List<T> に、map<K, V> はデフォルト emptyMap() 付きの Map<K, V> になります。単一のネストされたメッセージフィールドはデフォルト null の nullable(?)— proto3 の has-value セマンティクスに合わせています。

フィールド名は proto の snake_case から Kotlin の camelCase へ変換されます(order_idorderId)— 公式の Kotlin スタイルに基づく標準的な Kotlin コーディング規約です。クラス名と enum 名は PascalCase のままです。各 enum は Int のバッキング値を持つ enum class になります。変換はすべてブラウザ内で完結します — あなたの .proto はページから出ません。

使い方

3 ステップ。出力はそのまま貼り付けられる Kotlin です。

1

.proto スキーマを貼り付ける

左のエディタにスキーマを置きます。先頭の syntax = "proto3"; はあっても無くても構いません。ネストされた message ブロック、enum 宣言、oneofmap<K, V>、フィールドオプションすべてに対応しています。

Kotlin のコーディング規約はプロパティに camelCase を好みます — コンバーターはそれを行います。元の snake_case 名のままが良ければ(一部のシリアライズライブラリはフィールド名の完全一致を要求します)、出力で find-replace してください。

2

Kotlin の出力を読む

右側: 各メッセージはすべてのプロパティにデフォルト値付きの data class になります。各 enum は enum class(val value: Int) になり、wire フォーマットをラウンドトリップできます。トップレベルのみ(ネストなし)— 1 ファイルに入れるのも分割するのも楽です。

3

プロジェクトに組み込む

ファイルをプロジェクトに置き、package 宣言を追加して import します。Android や JVM 上の本物の gRPC コードでは、marshal メソッドとスタブを得るために結局 grpc-kotlin codegen を回したくなるはずです。この出力は型付きの JSON ハンドリング、構造体スケッチ、レビュー用です。

本当に時短になる場面

バックエンドの .proto から Android の型をスケッチする

Android アプリが gRPC バックエンドと通信する。.proto の所有はバックエンドチーム。codegen を組まずに ViewModel を型付けするための data class の形が欲しい。貼り付けて Models.kt に落とせば、もう型付き完了です。

サーバーサイド Kotlin が JSON エンコードの Protobuf をパースする

サーバーサイド Kotlin(Ktor / Spring Boot)が proto3 JSON エンコーディングに従う JSON を消費する。一致する data class が必要です。.proto を貼り付け、Kotlin 出力をコピーし、お好みのシリアライザに繋ぐだけ。

Protobuf API の変更レビュー

チームメイトがメッセージにフィールドを追加した。新しい .proto を貼り付け、Kotlin 出力を現在の Models.kt と diff し、ツールチェーン全体を立ち上げずに焦点を絞ったレビューを残せます。

使い捨てスクリプトと素早いプロトタイプ

gRPC-gateway を叩く 50 行の Kotlin スクリプト。そのために grpc-kotlin と protoc を組むのはやり過ぎ。ここで data class を生成して放り込みます。

よくある質問

これは protoc-gen-kotlin の代わりですか?

いいえ。本物の codegen は marshal/unmarshal メソッド、ディスクリプタ、gRPC のスタブを生成します。このツールは data class の形だけを出力します。プロダクションの gRPC コードには grpc-kotlin を回してください。これはスケッチ、JSON のパース、レビュー、使い捨てスクリプト用です。

単一のメッセージフィールドが nullable なのはなぜ?

proto3 ではメッセージフィールドに「has value」セマンティクスがあり、未設定があり得ます。最も綺麗な Kotlin 同等表現はデフォルト null の nullable プロパティです。データが常にこれらのフィールドを埋めると分かっているなら、? とデフォルトを外してください — シンプルな find-replace です。

uint32 と uint64 はどう扱われますか?

両方とも符号付きの型(IntLong)にマップされます。Kotlin には 1.5 以降に安定版の UIntULong がありますが、符号付きの方が既存のシリアライズライブラリやほとんどの Android コードベースとの相性が良いです。符号なしのバリアントが特に必要なら、出力で差し替えてください。

enum はどのように出力されますか?

各 enum は enum class WithValue(val value: Int) になり、wire フォーマットの整数を保持できます。各値には元の proto 名(例: ORDER_STATUS_PENDING)が付きます — Kotlin の enum エントリは慣例的に SCREAMING_SNAKE_CASE なので、これと一致します。

フィールド名はどう変換されますか?

Kotlin のコーディング規約に従って snake_casecamelCaseorder_idorderId に、customer_namecustomerName になります。クラスと enum の名前は proto そのままの PascalCase です。

ネストされたメッセージは扱えますか?

はい — ネストされた message ブロックは出力でトップレベルの data class 宣言に平坦化されます。ファイルを読みやすく保ち、複数ファイルへの分割も楽です。Kotlin のネストされたクラスが好みなら、手で包んでください。

関連ツール

Protobuf と Kotlin を扱っているなら、これらと相性が良いです: