Сериализация необязательных полей в protobuf-net

У меня есть рабочий 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 from 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. Пробовал как с ним, так и без ...


person David Hedlund    schedule 11.05.2010    source источник


Ответы (1)


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

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

person Marc Gravell    schedule 11.05.2010
comment
Приветствую за быстрый ответ. Я сгенерировал код из командной строки. Свойство *Specified, похоже, не влияет на результат, независимо от того, установил ли я его на true или false. То же самое и для метода ShouldSerialize*, как предлагается здесь: stackoverflow .com / questions / 1379332 / - person David Hedlund; 11.05.2010
comment
Я нашел фрагмент кода в сериализаторе java, который проверяет if (hasAppId()) { output.writeString(4, getAppId()); }, поэтому действительно кажется, что полностью исключить его из сериализованного вывода - это то, что я хочу сделать. - person David Hedlund; 11.05.2010
comment
@ Дэвид Хедлунд ОК; У меня есть твой пример - посмотрю, что с ним можно сделать. Для информации, у вас есть простой пример данных с выводом java, чтобы я мог подтвердить результат? - person Marc Gravell; 11.05.2010
comment
@Mark Gravell: Чтобы предоставить вам образцы данных, я создал несколько простых объектов и сравнил результаты. Затем я заметил, что ошибался в том, где появились несоответствия. Раньше меня сбивало с толку тот факт, что "" было значением по умолчанию, и что явная установка "" вызвала ту же ошибку в Java. Вот настоящая сделка: установка "" в java приводит к ее сериализации, что дает мне 403. Установка "" в C # вообще не сериализовалась, но другая ошибка продолжала давать мне 403. В C # это было другое значение, которое по умолчанию было 0 и поэтому было не сериализовано, - person David Hedlund; 11.05.2010
comment
... когда это должно быть. Я решил это, сделав это обязательным полем. Я принимаю ваш ответ, поскольку он вместе с последующим обсуждением привело меня к решению, а также потому, что *Specified { get; set; } намек, о котором я совершенно не знал. Большое спасибо за ваше время (и за отличную библиотеку) - person David Hedlund; 11.05.2010