2017-03-06 43 views
8

Potrzebuję podać komunikat z opcjonalnym polem w protobuf (składnia proto3). Pod względem proto 2 składni komunikat chcę wyrazić to coś w rodzaju:Jak zdefiniować pole opcjonalne w protobuf 3

message Foo { 
    required int32 bar = 1; 
    optional int32 baz = 2; 
} 

Z mojego zrozumienia „opcjonalne” koncepcja została usunięta z składni proto 3 (wraz z wymaganą koncepcji). Chociaż nie jest jasne, alternatywa - użycie wartości domyślnej do stwierdzenia, że ​​pole nie zostało określone od nadawcy, pozostawia niejednoznaczność, jeśli domyślna wartość należy do prawidłowej domeny wartości (należy rozważyć na przykład typ boolowski).

Więc jak mam zakodować powyższy komunikat? Dziękuję Ci.

+0

Czy podejście poniżej rozwiązanie dźwięku? wiadomość NoBaz { } wiadomość Foo { int32 bar = 1; oneof baz { NoBaz undefined = 2; int32 defined = 3; }; } – MaxP

Odpowiedz

17

W protokole proto3 wszystkie pola są "opcjonalne" (ponieważ nie jest to błąd, jeśli nadawca nie może ich ustawić). Ale pola nie są już "zerowe", ponieważ nie można odróżnić pola, które jest jawnie ustawione na jego wartość domyślną, a nie było ustawione w ogóle.

Jeśli potrzebujesz "zerowego" stanu (i nie ma wartości poza zakresem, której możesz użyć do tego), musisz zamiast tego zakodować to jako osobne pole. Na przykład, można zrobić:

message Foo { 
    bool has_baz = 1; 
    int32 baz = 2; 
} 

Alternatywnie, można użyć oneof:

message Foo { 
    oneof baz { 
    bool baz_null = 1; // always set this to "true" when using 
    int32 baz_value = 2; 
    } 
} 

Wersja oneof jest bardziej wyraźny i bardziej wydajny na drucie, ale wymaga zrozumienia, jak działa oneof wartości.

Wreszcie inną, całkowicie rozsądną opcją jest trzymanie się proto2. Proto2 nie jest przestarzałe, a wiele projektów (w tym Google) w bardzo dużym stopniu zależy od funkcji proto2, które są usuwane w protokole proto3, dlatego prawdopodobnie nigdy się nie zmienią. Tak więc bezpiecznie można go używać w najbliższej przyszłości.

+0

Podobny do twojego rozwiązania, w moim komentarzu, zaproponowałem, aby użyć theof z wartością rzeczywistą i typu zerowego (pusta wiadomość). W ten sposób nie zawracasz sobie głowy wartością boolowską (która nie powinna być istotna, ponieważ jeśli istnieje wartość boolowska, to nie ma wartości baz_) Poprawność? – MaxP

+2

@MaxP Twoje rozwiązanie działa, ale polecam wartość boolowską nad pustym komunikatem. Albo zajmie dwa bajty na przewodzie, ale pusta wiadomość zajmie znacznie więcej procesora, pamięci RAM i wygenerowanego nadpisania kodu do obsługi. –

+2

Znajduję komunikat Foo { oneof baz { int32 baz_value = 1; } } działa całkiem dobrze. – CyberSnoopy

0

podstawie odpowiedzi Kenton, w jeszcze prostsze rozwiązanie pracy wygląda następująco:

message Foo { 
    oneof optional_baz { // "optional_" prefix here just serves as an indicator, not keyword in proto2 
     int32 baz = 1; 
    } 
}