Сериализация необязательных полей в protobuf-net - PullRequest
2 голосов
/ 11 мая 2010

У меня есть работающий Java-клиент, который связывается с Google через сериализованные сообщения ProtoBuf. В настоящее время я пытаюсь перевести этого клиента на C #.

У меня есть файл .proto, где параметр appId является необязательной строкой. Его значение по умолчанию в представлении C #, генерируемое библиотекой protobuf-net, является пустой строкой, как и в представлении java того же файла.

message AppsRequest {
  optional AppType appType = 1;
  optional string query = 2;
  optional string categoryId = 3;
  optional string appId = 4;
  optional bool withExtendedInfo = 6;
}

Я обнаружил, что когда я явно устанавливаю appId в "" в клиенте java, клиент перестает работать (403 Bad Request от Google). Когда я явно устанавливаю appId в null в клиенте java, все работает, но только потому, что для hasAppId задано значение false (я не знаю, как это повлияет на сериализацию).

В клиенте C # я всегда получаю 403 ответа. Я не вижу никакой логики за различием между не установкой значения и установкой значения по умолчанию, которое, кажется, имеет все значение в Java-клиенте. Поскольку выходные данные всегда являются двоичным потоком, я не уверен, что успешные сообщения Java сериализуются с пустой строкой или не сериализуются вообще.

В клиенте C # я попытался установить IsRequired в значение true для атрибута ProtoMember, чтобы заставить их сериализоваться, и я попытался установить значение по умолчанию в null и явно установить "", так что я совершенно уверен, что попробовал некоторую конфигурацию, где значение сериализуется. Я также поиграл с ProtoBuf.ProtoIgnore и в какой-то момент вообще удалил параметр appId, но мне не удалось избежать 403 ошибок в C #.

Я попытался вручную скопировать сериализованную строку из Java, и это решило мои проблемы, поэтому я уверен, что остальная часть HTTP-запроса работает, и ошибка может быть отслежена для сериализованного объекта.

Моя сериализация просто так:

var clone = ProtoBuf.Serializer.DeepClone(request);

MemoryStream ms = new MemoryStream(2000);
ProtoBuf.Serializer.Serialize(ms, clone);

var bytearr = ms.ToArray();
string encodedData = Convert.ToBase64String(bytearr);

Я признаю, что не совсем уверен в том, что делает DeepClone. Я пробовал как с, так и без него ...

1 Ответ

1 голос
/ 11 мая 2010

Звучит так, как будто мы хотим заставить его исключить; Для начала, вы можете попробовать использовать параметр «Detemissing» в генерации кода. Это возможно из среды IDE и командной строки, но по-другому (дайте мне знать, какой вы используете, и я добавлю больше).

Другой аналогичный вариант - добавить (в частичном классе) bool {memberName}Specified {get;set;}. Существует открытый отчет о странности, включающий пустые строки по умолчанию, который я смотрю.

...