InvalidProtocolBufferException в клиенте Java при десериализации данных protobuf с сервера C ++ - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть сообщение protobuf, подобное этому:

message Update {
  Path path = 1;                      // The path (key) for the update.
  Value value = 2 [deprecated=true];  // The value (value) for the update.
  TypedValue val = 3;                 // The explicitly typed update value.
}

// TypedValue is used to encode a value being sent between the client and
// target (originated by either entity).

message TypedValue {
    oneof value {
        string string_val = 1;            // String value.
        int64 int_val = 2;                // Integer 
        ....
        google.protobuf.Any any_val = 9;  // protobuf.Any encoded bytes.
        ....
  }
}

На стороне сервера (C ++) мы устанавливаем это поле следующим образом (LLDP является внешним классом, а интерфейсы внутри него):

   openconfig_lldp::Lldp out;
   GetLldpProto(&out);

   update->mutable_val()->mutable_any_val()->PackFrom(out.interfaces());

На стороне клиента (Java) мы извлекаем это поле следующим образом:

OpenconfigLldp.Lldp.Interfaces interfaces = update.getVal().getAnyVal().unpack(OpenconfigLldp.Lldp.Interfaces.class);

Это вызывает исключение InvalidProtocolBufferException.Когда я сбрасываю «обновление» в моем клиенте Java, я вижу это:

path {
  elem {
    name: "lldp"
  }
  elem {
    name: "interfaces"
  }
}
val {
  any_val {
    type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"
    value: "\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/1\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/2\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/3\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/4\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n"
  }
}

Мне кажется, что type_url правильный.Что я здесь не так делаю?

Спасибо за ваше время.

РЕДАКТИРОВАТЬ # 1:

Я посмотрел на строку исключения.Это «Тип сообщения Any не соответствует данному классу.»

Тот же файл протока используется для C ++ и Java, но я вижу «openconfig_lldp.Lldp.Interfaces» в C ++, где, как, онтакое "OpenconfigLldp.Lldp.Interfaces" в Java.Необходимо выяснить, почему ..

РЕДАКТИРОВАТЬ # 2:

Используется тот же файл .proto.В данном случае это:

openconfig_lldp.proto
---------------------
syntax = "proto3";

package openconfig.openconfig_lldp;

message Lldp {
    message Config {
        ....
        ....
    }
    ....
    ....
}

В случае с Java я вижу родительский класс как OpenconfigLldp в пакете с именем openconfig_lldp.

package openconfig.openconfig_lldp;

public final class OpenconfigLldp {
  private OpenconfigLldp() {}
  ....
  ....
  /**
   * Protobuf type {@code openconfig.openconfig_lldp.Lldp}
   */
  public  static final class Lldp extends com.google.protobuf.GeneratedMessageV3 implements
    // @@protoc_insertion_point(message_implements:openconfig.openconfig_lldp.Lldp)
   ....
   ....
}

В C ++ я неувидеть любой класс с именем «OpenconfigLldp» генерируется.Вместо этого это просто "Lldp"

Итак, type_url в Any.protobuf не соответствует.На стороне C ++ это выглядит как

type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"

В то время как на стороне Java я использую:

OpenconfigLldp.Lldp.Interfaces interfaces = update.getVal().getAnyVal().unpack(OpenconfigLldp.Lldp.Interfaces.class);

У кого-нибудь есть мысли о том, почему в выводе Java Protoc есть класс-оболочка?

РЕДАКТИРОВАТЬ # 3

Видимо, похоже, что это из-за "external_class_name".В коде Java у меня есть внешний класс "OpenconfigLldp".

Формат type_url:

type.googleapis.com/packagename.messagename

Итак, код C ++ устанавливает это в openconfig_lldp.Lldp.Interfaces.Но это сопоставляется с OpenconfigLldp.Lldp.Interfaces в Java.

Как я могу обойти это?

FINAL EDIT и FINAL QUESTION

После некоторого копания эточто я узналПо умолчанию type_url:

type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"

На стороне Java я рассмотрел реализацию Any.Он пытается сравнить это с:

openconfig.openconfig_lldp.Lldp.Interfaces 

Я выяснил это, напечатав:

Lldp.Interfaces defaultInstance = (Lldp.Interfaces)Internal.getDefaultInstance(Lldp.Interfaces.class);
logger.info("full descriptor name: " + defaultInstance.getDescriptorForType().getFullName());

Итак, я взломал сторону C ++ для отправки:

update->mutable_val()->mutable_any_val()->set_type_url(std::string("type.googleapis.com/openconfig.openconfig_lldp.Lldp.Interfaces"));

Итак, я думаю, что я знаю, что здесь происходит!

Спасибо за чтение всех изменений.

1 Ответ

0 голосов
/ 29 сентября 2018

Я не уверен, правильно ли я понимаю, что происходит - в идеале, квалифицированные имена должны быть в пространствах имен буфера протокола - не должно иметь значения отображение для конкретного языка.

Если вопрос все еще открыт, яЯ бы порекомендовал перенести ядро ​​в верхнюю часть, сохранив правки как "то, что я сделал до сих пор".

Возможно, это какая-то ошибка, которую можно обойти с помощью следующих параметров:

  • java_multiple_files
  • java_outer_classname

Подробнее об этих параметрах можно узнать здесь: https://developers.google.com/protocol-buffers/docs/proto3

...