2015-02-16 7 views
17

Ich habe ein bestehendes System, das protobuf-basierte Kommunikationsprotokoll zwischen GUI und Server verwendet. Jetzt möchte ich etwas Persistenz hinzufügen, aber im Moment werden Protobuf-Nachrichten direkt in benutzerdefinierte Objekte von Drittanbietern konvertiert.Java: JSON -> Protobuf & Rückkonvertierung

Gibt es eine Möglichkeit proto Nachrichten json, zu konvertieren, die dann in der Datenbank beibehalten werden könnten.

N.B .: Ich mag keine Idee, binäre Protobuf in Datenbank zu schreiben, weil es eines Tages mit neueren Versionen nicht abwärtskompatibel werden und das System auf diese Weise brechen kann.

+1

Was genau bedeuten, meinen Sie „, weil es eines Tages auch mit neueren Versionen nicht rückwärtskompatibel geworden "? Und was lässt Sie glauben, dass JSON eher rückwärtskompatibel bleibt? Sprechen Sie über neuere Versionen Ihres Proto-Schemas oder neuere Versionen von Protokollpuffern im Allgemeinen? Meine Erfahrung ist, dass das Speichern von Protokollpuffern absolut in Ordnung ist. –

+1

Beachten Sie, dass Protokollpuffer 3 (derzeit in der Betaversion) JSON direkt unterstützen. –

+0

Siehe auch https://stackoverflow.com/questions/2544580/is-there-a-standard-mapping-between-json-and-protocol-buffers – Raedwald

Antwort

22

Wir verwenden zur Zeit protobuf-java-format, um unsere Protobuf-Nachrichten (beliebige Unterklassen von Message) in ein JSON-Format zu konvertieren, um sie über unsere Web-API zu senden.

einfach tun:

JsonFormat.printToString(protoMessage) 
+0

Dies ist sehr hilfreich. Es wäre auch hilfreich, wenn Sie die API teilen könnten, um einen JSON-Dump in einen Protokollpuffer zu konvertieren. – vanguard69

+0

Diese Bibliothek scheint tot zu sein, da sie in Google Code-Archiven liegt und nicht in GitHub exportiert wird. Wichtige Probleme sind noch offen –

+1

@LouisCAD ja, aber ich denke, jetzt ist es in https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/util/JsonFormat – helt

23

ich nicht viel wie eine Idee von binären protobuf zur Datenbank zu schreiben, weil es eines Tages auch mit neueren Versionen nicht rückwärtskompatibel werden und brechen das System auf diese Weise .

Converting protobuf zu JSON für die Lagerung und dann wieder auf Last protobuf ist viel mehr wahrscheinlich Kompatibilitätsprobleme zu schaffen, denn:

  • Wenn der Prozess, der die Umwandlung durchführt, nicht mit dem eingebauten wird letzte Version des protobuf-Schemas, dann wird die Konvertierung stillschweigend alle Felder löschen, von denen der Prozess nichts weiß. Dies gilt sowohl für das Speichern als auch für das Laden.
  • Auch mit dem neuesten verfügbaren Schema kann JSON < -> Protobuf-Konvertierung bei Vorhandensein von ungenauen Gleitkommawerten und ähnlichen Eckfällen verlustbehaftet sein.
  • Protobufs haben tatsächlich (etwas) stärkere Rückwärtskompatibilitätsgarantien als JSON. Wie bei JSON ignorieren alte Clients das Feld, wenn Sie ein neues Feld hinzufügen. Im Gegensatz zu JSON erlaubt Protobufs die Deklaration eines Standardwerts, was es für neue Clients etwas einfacher macht, mit alten Daten umzugehen, die ansonsten das Feld nicht enthalten. Dies ist nur ein kleiner Vorteil, aber ansonsten verfügen Protobuf und JSON über entsprechende Abwärtskompatibilitätseigenschaften, sodass Sie beim Speichern in JSON keine Vorteile hinsichtlich der Rückwärtskompatibilität erhalten.

Mit allem, was gesagt, gibt es viele Bibliotheken gibt für protobufs zu JSON Konvertierung, in der Regel auf der Reflexions Schnittstelle Protobuf gebaut (nicht mit der Java-Reflexion-Grenzfläche verwechselt werden; Protobuf Reflexion durch die com.google.protobuf.Message Schnittstelle angeboten wird) .

6

zu Ophir s Antwort Hinzufügen ist JsonFormat verfügbar, noch bevor protobuf 3.0. Die Vorgehensweise unterscheidet sich jedoch ein wenig.

In Protobuf 3.0+ ist die JsonFormat Klasse ein Singleton und damit so etwas wie die unten

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

In Protobuf 2.5+, sollte die unten arbeiten

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

Hier ein Link zu einer tutorial ist ich schrieb, dass Verwendungen die JsonFormat-Klasse in einem TypeAdapter, die für ein GsonBuilder-Objekt registriert werden kann. Sie können dann die toSon- und fromJson-Methoden von Gson verwenden, um die Proto-Daten in Java und zurück zu konvertieren.

Antwort auf jean. Wenn wir die protobuf-Daten in einer Datei haben und sie in ein protobuf-Nachrichtenobjekt analysieren möchten, verwenden Sie die Merge-Methode TextFormat class. Siehe unten stehende Snippet:

// 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

Und dies für PROTO zu JSON in 3.0+: 'JsonFormat.printer(). Print (MessageOrBuilder)' –

1

Versuchen JsonFormat.printer().print(MessageOrBuilder), sieht es gut für proto3. Es ist jedoch unklar, wie die eigentliche Nachricht protobuf (die als Java-Paket meiner Wahl in der .proto-Datei definiert ist) in ein com.google.protbuf.Message-Objekt konvertiert wird.

2

Für protobuf 2.5, verwenden, um die Abhängigkeit:

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

Dann verwenden Sie den Code:

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