web-dev-qa-db-ja.com

プロトコルバッファ3にフィールドが設定されているかどうかを確認する

Javaアプリケーションをプロトコルバッファ2からプロトコルバッファ3に移行しています。

Proto 2では、フィールドが設定されているかどうかを確認するためにhasfield()メソッドがあり、例としてJava生成されるコードは次のとおりです。

public boolean hasText() {
  return ((bitField0_ & 0x00000004) == 0x00000004);
}

ただし、プロト3では削除されています。プロト3でフィールドが設定されているかどうかをどのように確認しますか?

8
user1798617

提案されたアプローチの1つを以下に示します here

# NOTE: As of proto3, HasField() only works for message fields, not for
#       singular (non-message) fields. First try to use HasField and
#       if it fails (with a ValueError) we manually consult the fields.
try:
    return message_pb.HasField(property_name)
except ValueError:
    all_fields = set([field.name for field in message_pb._fields])
    return property_name in all_fields

また、同じページから:

Proto3では、スカラーフィールドのフィールドプレゼンスは存在しません。 proto3のメンタルモデルは、C++またはGo構造体である必要があります。整数と文字列の場合、設定されているかどうかなどはありません。常に値があります。サブメッセージの場合、これはNULLの可能性があるサブメッセージインスタンスへのポインタです。そのため、その存在をテストできます。

4
P.W

Proto3で行われた設計上の決定のために推奨されないアプローチは、標準値をチェックすることだと思います。フィールドが設定されているかどうかを明示的に確認することはできません。説明されているようにmsg._fieldsへのアクセスはお勧めしません ここ 残っているのは、フィールドが標準値に設定されているかどうかを確認することだけです。

if msg.textfield.isEmpty() {
    //assume textfield is not set
}
1
Gigi

Proto3でこれについて私が見た最良の提案は、フィールドをシングルトンoneofでラップすることです。これにより、proto2と同様に、存在の有無を再度確認できます。

message blah
{
    oneof foo_ { sint32 foo = 1; }
}

Python生成されたコードでは、fooをスカラーとして直接操作できるので、oneofの内部にないかのように、これは非常にスムーズです。

残念ながら、Javaの場合、oneofのサポートははるかに醜いと思います。Googleは、意図的にhasFoo()によって生成されたクラス関数をproto3から削除しました。そのため、代わりにoneofのgetFooCase()を参照する必要があります。有無を確認します。

https://developers.google.com/protocol-buffers/docs/reference/Java-generated#oneof-fields

はい、私はこれらの手段がたくさんあること、そして彼らがもたらすあらゆる面倒な手間を理解しています。プラスの面では、配線にオーバーヘッドはありません。

私が見た2番目に良い提案は、サブメッセージの有無がまだサポートされているため、サブメッセージを使用してスカラーをラップすることです。 google.protobuf.wrappers.protoにはWell Known Types(WKT)があります。それらを使用すると、ラップされたスカラーが含まれているサブメッセージが存在しないかのようにラップされたスカラーを簡単に操作できる、優先言語で特別な扱いを受けることもできます(または私は読んだので、この点については完全に確信が持てません) )。

0
jschultz410