2015-02-16 9 views
17

Mam istniejący system, który używa protokołu komunikacyjnego opartego na protobuf między GUI a serwerem. Teraz chciałbym dodać trochę uporczywości, ale w tej chwili komunikaty protobuf są konwertowane bezpośrednio na niestandardowe obiekty stron trzecich.Java: JSON -> Protobuf i konwersja z powrotem

Czy istnieje sposób przekonwertować proto wiadomości do json, które mogą być następnie utrzymywała się do bazy danych.

N.B .: robię nie tak jak pomysł pisania binarną Protobuf do bazy danych, ponieważ może pewnego dnia stać się nie wstecznie kompatybilne z nowszymi wersjami i złamać system w ten sposób.

+1

Co dokładnie masz na myśli przez „bo może pewnego dnia stać się nie wstecznie kompatybilne z nowszymi wersjami "? A co sprawia, że ​​JSON będzie bardziej prawdopodobne, że będzie kompatybilny wstecz? Czy mówisz o nowszych wersjach twojego schematu proto lub ogólnie o nowszych wersjach buforów protokołów? Z doświadczenia wiem, że przechowywanie buforów protokołów jest absolutnie w porządku ... –

+1

Należy zauważyć, że bufory protokołów 3 (obecnie w wersji beta) będą bezpośrednio wspierać JSON. –

+0

Zobacz także https://stackoverflow.com/questions/2544580/is-there-a-standard-mapping-between-json-and-protocol-buffers – Raedwald

Odpowiedz

22

Aktualnie używamy protobuf-java-format do konwersji naszych wiadomości Protobuf (podklasa dowolna z Message) do formatu JSON, aby przesłać nasz web API.

Wystarczy zrobić:

JsonFormat.printToString(protoMessage) 
+0

Jest to bardzo pomocne. Byłoby również przydatne, gdybyś mógł udostępnić interfejs API do konwersji zrzutu JSON do bufora protokołu. – vanguard69

+0

Ta biblioteka wydaje się być martwa, ponieważ znajduje się w archiwach Google Code, nie jest eksportowana do GitHub, a ważne problemy wciąż są otwarte. –

+1

@LouisCAD tak, ale myślę, że teraz jest na https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/util/JsonFormat – helt

23

nie mam podobny pomysł pisania binarną Protobuf do bazy danych, ponieważ może pewnego dnia stać się nie wstecznie kompatybilne z nowszymi wersjami i złamać system w ten sposób .

Konwersja Protobuf do JSON do przechowywania, a następnie z powrotem do Protobuf na obciążenie jest znacznie więcej może powodować problemy ze zgodnością, ponieważ:

  • Jeśli proces, który wykonuje konwersję nie jest zbudowany z najnowszą wersję schematu protobuf, a następnie konwersja spowoduje po cichu usunięcie wszystkich pól, o których proces nie wie. Dotyczy to zarówno składowania, jak i załadunku.
  • Nawet z najnowszym dostępnym schematem JSON < -> Konwersja Protobuf może być stratna w przypadku nieprecyzyjnych wartości zmiennoprzecinkowych i podobnych narożników.
  • Protobufy mają (nieco) silniejsze gwarancje kompatybilności wstecznej niż JSON. Podobnie jak w przypadku JSON, jeśli dodasz nowe pole, starzy klienci będą go ignorować. W przeciwieństwie do JSON, Protobuf pozwala na deklarowanie wartości domyślnej, co może nieco ułatwić nowym klientom radzenie sobie ze starymi danymi, które w innym przypadku nie mają pola. Jest to tylko niewielka zaleta, ale poza tym Protobuf i JSON mają równoważne właściwości kompatybilności wstecznej, dlatego nie zyskujesz żadnych korzyści wstecznej kompatybilności ze składowania w JSON.

Ze wszystkim, co powiedział, istnieje wiele bibliotek tam do konwersji protobufs do JSON, zwykle zbudowany na interfejsie refleksji Protobuf (nie mylić z interfejsem refleksji Java; Protobuf odbicie jest oferowany przez interfejs com.google.protobuf.Message) .

6

Dodawanie do Ophir s odpowiedzi JsonFormat jest dostępny nawet przed protobuf 3.0. Jednak sposób na to różni się nieco.

W Protobuf 3.0+, klasa JsonFormat jest pojedyncza, a zatem zrobić coś jak poniżej

String jsonString = ""; 
JsonFormat.parser().ignoringUnknownFields().merge(json,yourObjectBuilder); 

W Protobuf 2.5+, poniżej powinny działać

String jsonString = ""; 
JsonFormat jsonFormat = new JsonFormat(); 
jsonString = jsonFormat.printToString(yourProtobufMessage); 

Oto link do tutorial pisałem, że zastosowania klasa JsonFormat w TypeAdapter, która może zostać zarejestrowana w obiekcie GsonBuilder. Następnie można użyć metod Gson's toJson i fromJson do konwersji danych proto na język Java iz powrotem.

Odpowiadając na jean. Jeśli mamy dane protobuf w pliku i chcemy je przetworzyć w obiekt komunikatu protobuf, użyj klasy merge TextFormat. Patrz poniższy fragment:

// Let your proto text data be in a file MessageDataAsProto.prototxt 
// Read it into string 
String protoDataAsString = FileUtils.readFileToString(new File("MessageDataAsProto.prototxt")); 

// Create an object of the message builder 
MyMessage.Builder myMsgBuilder = MyMessage.newBuilder(); 

// Use text format to parse the data into the message builder 
TextFormat.merge(protoDataAsString, ExtensionRegistry.getEmptyRegistry(), myMsgBuilder); 

// Build the message and return 
return myMsgBuilder.build(); 
+1

A ten dla PROTO dla JSON w wersji 3.0+: 'JsonFormat.printer(). Print (MessageOrBuilder)' –

1

Spróbuj JsonFormat.printer().print(MessageOrBuilder), dobrze wygląda na proto3. Nie jest jednak jasne, w jaki sposób przekonwertować aktualną wiadomość o nazwie protobuf (która jest dostępna jako wybrany pakiet java zdefiniowany w pliku .proto) do obiektu com.google.protbuf.Message.

2

Dla Protobuf 2.5, użyj Zależność:

"com.googlecode.protobuf-java-format" % "protobuf-java-format" % "1.2" 

Następnie użyj kodu:

com.googlecode.protobuf.format.JsonFormat.merge(json, builder) 
com.googlecode.protobuf.format.JsonFormat.printToString(proto)