protobuf typeに値が入っているか確認するにはgoogle/protobuf/wrappers.protoをつかうとよい


今回のエントリも前回に続きprotobufの数あるtypeの中から1つの使い方まとめていきたい。今回は google/protobuf/wrappers.protoをまとめていく。
protobufのtypeのなかにはプリミティブなtypeとしてstringuint32, uint64などが用意されている。プリミティブなtypeをリクエストに定義した場合、リクエストに値を定義しないとデフォルト値がセットされる。

Language Guide (proto3)  |  Protocol Buffers  |  Google Developers

gRPC Clientが明示的に値をセットしないとuint32では0値をgRPC Serverで受け取ることになる。

次のようなリクエストにつかうprotoを定義するケースを考えていく。

1
2
3
message TaskListInbound {
  uint32 page = 1;
}

gRPC Clientからは pageに値がセットされていなければpageの値を10にServer側でセットするとしよう。

1
2
3
4
val page = when {
    request.page == UInt32Value.getDefaultInstance().value -> DEFAULT_PAGE_LIMIT
    else -> request.page
}

UInt32Value.getDefaultInstance().value からuint32のデフォルト値をとることで判定をしている。pageのケースであればこれでも良いかもしれないが、デフォルト値の0でも良いケースではデフォルト値判定をする必要がなくなるし、Patchのようなリクエストメソッドを提供したい場合などはprotoに定義したフィールドに値がセットされたのかどうかを素直に判定したい。

そのようなケースに有効なprotobufのtypeにgoogle/protobuf/wrappers.protoが用意されている。

protobuf typeに値が入っているか確認できるwrappers.proto

wrappers.protoはプリミティブなtypeに対応している。

protoの定義は次のように書ける

1
2
3
message TaskListInbound {
  google.protobuf.UInt32Value page = 1;
}

値がセットされているかどうかもhasFiledName()の関数が用意されている。

1
2
3
4
val page = when {
    request.hasPage() -> request.page.value
    else -> DEFAULT_PAGE_LIMIT
}

wrappers.protoのUInt32Valueとプリミティブなuint32を使い分けることでgRPC Clientのリクエストパラメータをオプションか必須であるか明示的に定義することができる。

コード

コードは次のレポジトリにコミットしてあります。