2012-02-07 1 views
3

Я определяю сообщение ProtoBuf, где я хочу иметь поле «nullable» - то есть, я хочу различать поле, имеющее значение и не имеющее значения. В качестве конкретного примера предположим, что у меня есть поля «x» и «y» для записи координат какого-либо объекта. Но в некоторых случаях координаты не известны. Следующее определение будет не работу, потому что если х или у не определены, то они по умолчанию к нулю (что является допустимым значением):Каков предпочтительный способ кодирования поля «nullable» в protobuf?

message MyObject { 
    optional float x = 1; 
    optional float y = 2; 
} 

Одним из вариантов было бы добавить логическое поле записи, является ли соответствующий значение поля известно или нет. Т.е .:

message MyObject { 
    optional bool has_x = 1; // if false, then x is unknown. 
    optional bool has_y = 2; // if false, then y is unknown. 
    optional float x = 3; // should only be set if has_x==true. 
    optional float y = 4; // should only be set if has_y==true. 
} 

Но это накладывает некоторую дополнительную бухгалтерию - например, когда заданное значение Х-FIELD, я должен всегда помнить также установить has_x. Другим вариантом было бы использовать значение списка, с конвенцией, что список всегда имеет либо длину 0 или длину 1:

message MyObject { 
    repeated float x = 1; // should be empty or have exactly 1 element. 
    repeated float y = 2; // should be empty or have exactly 1 element. 
} 

Но в данном случае, определение кажется немного вводит в заблуждение, а интерфейс не является намного лучше.

Есть ли третий вариант, который я не думал об этом лучше, чем эти два? Как вы справлялись с хранением полей с нулевым значением в protobuf?

ответ

2

Сообщения Protobuf имеют встроенное понятие «поля с нулевым значением». Интерфейс C++ содержит методы has_xxx и clear_xxx, чтобы проверить, было ли поле задано и не удалось установить поле, соответственно.

Эта функция поставляется «бесплатно» из-за того, что поля закодированы в сообщении с помощью «тегов». Отключенное поле просто «отсутствует» в закодированном сообщении.

+0

Вы уверены? В частности, если я кодирую сообщение и отправляю его по проводу, смогу ли я выделить объект, у которого его поле явно задано значением по умолчанию для объекта, чье поле никогда не было установлено ни на какое значение? См. Мой родственный вопрос: http://stackoverflow.com/questions/9168052/how-do-has-field-methods-relate-to-default-values-in-protobuf –

+1

Да. Вы должны прочитать, как кодируются протоколы protobuf: http://code.google.com/apis/protocolbuffers/docs/encoding.html. Сообщения кодируются как серия пар ключ/значение (это то, что для идентификатора/тега для каждого поля). Исключенные поля просто отсутствуют в закодированном сообщении. Если у вас есть три поля: a, b и c с метками 1, 2 и 3 соответственно, и вы кодируете сообщение только с «a», установленным на «42», тогда закодированное сообщение будет содержать «поле (1) = 42 ", и ничего больше. – JesperE

+3

Ответ JesperE может быть правдой в прошлом, но это определенно не так. – jordanbtucker

1

Имейте в виду NaN для каждого из типов, а затем используйте default (как показано ниже), чтобы установить его как значение. Это будет использоваться, если для данного поля ничего не указано.

optional float x = 1 [default = -1]; 
+4

Это работает только в том случае, если в домене этого типа есть некорректное значение. Например, для координаты -1 является вполне допустимым значением. В области «float» нет значения, которое не может быть реальной координатой. –

Смежные вопросы