protobuf 3에서 선택적 필드를 정의하는 방법
protobuf (proto3 구문)에 선택적 필드가있는 메시지를 지정해야합니다. proto 2 구문 측면에서 표현하고 싶은 메시지는 다음과 같습니다.
message Foo {
required int32 bar = 1;
optional int32 baz = 2;
}
내 이해에서 "선택적"개념이 구문 proto 3에서 제거되었습니다 (필수 개념과 함께). 대안은 명확하지 않지만 기본값을 사용하여 보낸 사람이 필드를 지정하지 않았 음을 나타내면 기본값이 유효한 값 도메인 (예 : 부울 유형을 고려)에 속하는 경우 모호함이 남습니다.
그렇다면 위의 메시지를 어떻게 인코딩해야합니까? 감사합니다.
proto3에서 모든 필드는 "선택 사항"입니다 (발신자가 설정에 실패해도 오류가 아님). 그러나 필드는 더 이상 "nullable"이 아닙니다. 필드가 명시 적으로 기본값으로 설정되는 것과 전혀 설정되지 않은 것 사이의 차이를 구분할 방법이 없기 때문입니다.
"null"상태가 필요하고이를 위해 사용할 수있는 범위를 벗어난 값이없는 경우 대신이를 별도의 필드로 인코딩해야합니다. 예를 들어 다음과 같이 할 수 있습니다.
message Foo {
bool has_baz = 1; // always set this to "true" when using baz
int32 baz = 2;
}
또는 다음을 사용할 수 있습니다 oneof
.
message Foo {
oneof baz {
bool baz_null = 1; // always set this to "true" when null
int32 baz_value = 2;
}
}
oneof
버전은 와이어에 대한 명시 적으로 더 효율적입니다하지만 어떻게 이해해야합니다 oneof
값이 작동합니다.
마지막으로 완벽하게 합리적인 또 다른 옵션은 proto2를 고수하는 것입니다. Proto2는 더 이상 사용되지 않으며 실제로 많은 프로젝트 (Google 내부 포함)가 proto3에서 제거 된 proto2 기능에 크게 의존하므로 전환되지 않을 가능성이 높습니다. 따라서 가까운 미래에 계속 사용하는 것이 안전합니다.
한 가지 방법은 oneof
수락 된 답변에서 제안 된대로 사용하는 것입니다.
또 다른 방법은 래퍼 개체를 사용하는 것입니다. Google에서 이미 제공하므로 직접 작성할 필요가 없습니다.
.proto 파일의 맨 위에 다음 가져 오기를 추가하십시오.
import "google/protobuf/wrappers.proto";
이제 모든 단순 유형에 특수 래퍼를 사용할 수 있습니다.
DoubleValue
FloatValue
Int64Value
UInt64Value
Int32Value
UInt32Value
BoolValue
StringValue
BytesValue
따라서 원래 질문에 답하기 위해 이러한 래퍼의 사용법은 다음과 같습니다.
message Foo {
int32 bar = 1;
google.protobuf.Int32Value baz = 2;
}
예를 들어 Java에서 다음과 같은 작업을 수행 할 수 있습니다.
if(foo.hasBaz()) { ... }
Kenton의 답변에 따르면 더 간단하면서도 작동하는 솔루션은 다음과 같습니다.
message Foo {
oneof optional_baz { // "optional_" prefix here just serves as an indicator, not keyword in proto2
int32 baz = 1;
}
}
To expand on @cybersnoopy 's suggestion here
if you had a .proto file with a message like so:
message Request {
oneof option {
int64 option_value = 1;
}
}
You can make use of the case options provided (java generated code):
So we can now write some code as follows:
Request.OptionCase optionCase = request.getOptionCase();
OptionCase optionNotSet = OPTION_NOT_SET;
if (optionNotSet.equals(optionCase)){
// value not set
} else {
// value set
}
you can find if one has been initialized by comparing the references with the default instance:
GRPCContainer container = myGrpcResponseBean.getContainer();
if (container.getDefaultInstanceForType() != container) {
...
}
Another way is that you can use bitmask for each optional field. and set those bits if values are set and reset those bits which values are not set
enum bitsV {
baz_present = 1; // 0x01
baz1_present = 2; // 0x02
}
message Foo {
uint32 bitMask;
required int32 bar = 1;
optional int32 baz = 2;
optional int32 baz1 = 3;
}
On parsing check for value of bitMask.
if (bitMask & baz_present)
baz is present
if (bitMask & baz1_present)
baz1 is present
ReferenceURL : https://stackoverflow.com/questions/42622015/how-to-define-an-optional-field-in-protobuf-3
'your programing' 카테고리의 다른 글
Windows Azure 웹 사이트 정리 (0) | 2021.01.05 |
---|---|
std :: vector에서 텍스트 파일로 데이터를 쓰는 빠른 방법 (0) | 2021.01.05 |
SWT에서 색상 설정 (0) | 2021.01.05 |
MVC에서 작업 결과로 XML 문자열을 반환하는 방법 (0) | 2021.01.05 |
실수로 바이러스를 만들었습니까? (0) | 2021.01.05 |