2013-06-13 5 views
0

Я читаю Google Protocol Buffers. Я хочу знать, могу ли я Serialize C++ object и отправить его на проводе на сервер Java и Deserialize там в java и наследовать поля.Сериализация/десериализация Google ProtoBuf

Скорее я хочу отправлять объекты с любого языка на Java Server. и десериализовать его там.

Предположит следующее моего .proto файл

message Person { 
    required int32 id = 1; 
    required string name = 2; 
    optional string email = 3; 
} 

Я побежал protoc на этом и создал C++ объект. В принципе сейчас я хочу отправить сериализованный поток на сервер java.

Здесь на стороне Java я могу deserialized поток, так что я могу узнать, есть 3 поля в потоке и его соответствующие name, type, and value

+0

Скомпилировать тот же файл '.proto' и сгенерировать Java-код. Затем используйте это при десериализации. – maba

+0

О, так это значит, что я использую это для модели типа клиент-сервер, мне также потребуется иметь .proto-файл на стороне сервера. Правильно !!!! – Avinash

+0

Ему нужно использовать флаг '--java_out', чтобы сделать код' protoc' java code IIRC – Petesh

ответ

2

Здесь на стороне Java я могу десериализован поток, так что я могу узнать, есть 3 поля в потоке и его соответствующие name, type и value

Вы должны знать схемы заранее. Во-первых, protobuf не передает имена; все, что он использует в качестве идентификаторов, - это числовой ключ (1, 2 и 3 в вашем примере) каждого поля.Во-вторых, он явно не указывает тип; в protobuf существует только очень мало типов проводников (varint, 32-bit, 64-bit, length-prefix, group); фактические данные типов отображаются на те, но вы не можете однозначно декодировать данные без схемы

  • varint является «некоторой формой целого», но может быть подписан, без знака или «зигзаг» (что позволяет отрицательным числа малой величины, которые должны быть дешево закодированы), и могут быть предназначены для представления любой ширины данных (64 бит, 32 бит и т. д.).
  • 32-разрядный может быть целым числом, но может быть подписан или без знака - или он может быть 32-разрядным числом с плавающей запятой
  • 64-битное может быть целым числом, но может быть подписано или без знака - или это может быть 64-битный floati ng-point number
  • длина-префикс может быть строкой UTF-8, последовательностью или необработанными байтами (без какого-либо особого значения), «упакованным» набором значений repeated некоторого примитивного типа (целое число, с плавающей запятой и т. д.), , или может быть структурированным под-сообщением в формате protobuf
  • группы - hoorah! это всегда однозначно! это может означать только одно; но одна вещь в значительной степени устаревшим Google :(

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

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

Что вы может сделать, это использовать парсер API для сканирования по данным, чтобы показать, что есть три поля, поле 1 является varint, поле 2 является длиной префикса, поле 3 является длиной префикса. Вы могли бы сделать образованные догадки о данных за его пределами (например, вы могли видеть, что декодер UTF-8 создает нечто похожее на текст и проверяет, что кодировка UTF-8 возвращает исходные байты, если это возможно это строка)

+0

hmmm Спасибо, Марк, я думаю, что Apache Avro имеет больше смысла, поскольку я не хочу иметь схему на стороне сервера, и Apache Avro говорит: «Когда данные Avro хранятся в файле, его схема хранится вместе с ним, чтобы файлы могли быть обработаны позже любой программой. Если программа, считывающая данные, ожидает другую схему, это может быть легко разрешено, так как обе схемы присутствуют ». – Avinash

+1

@ Avinash одна сноска к этому; протобуф.Прото-схема может быть упакована и передана как сообщение protobuf; но это не происходит по умолчанию, и нет никаких конкретных API-интерфейсов для этого прозрачного –

+0

Спасибо Marc, но даже если я передам схему, мне все равно придется генерировать код Java на стороне сервера, чтобы разобрать сериализованное сообщение Right! !!! – Avinash

1

Могу ли я сериализовать C++ объект и отправить его на проволоке к серверу Java и десериализуем там в java и исследуем поля.

Да, это самая цель протобуфа.

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

Имейте в виду, что буферы протокола не описываются самостоятельно, поэтому обеим сторонам вашего приложения необходимо иметь сериализаторы/десериализаторы, созданные из файла .proto.

+0

Они по умолчанию не описывают, но тривиально обертывать сообщение внутри другого сообщения, которое обеспечивает самостоятельную документацию. https://developers.google.com/protocol-buffers/docs/techniques#self-description – g19fanatic

+0

@ g19fanatic: Никогда не нужно было писать самоописательные сообщения, но это интересно. –

1

Вкратце: да, вы можете.

Вам нужно будет создать файлы .proto, которые определяют структуры данных, которые вы хотите разделить. Используя компилятор Google Protocol Buffers, вы можете генерировать интерфейсы и код деривации для ваших структур как для Java, так и для C++ (и почти любого другого языка, о котором вы можете думать).

Для передачи данных по проводам вы можете использовать, например, ZeroMQ, который является чрезвычайно универсальной основой коммуникации, которая также спортивные убиванием различного языкового API, среди них Java и C++.

См. this question for more details.

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