logo java json serialization persistence protocol-buffers

logo - Java: JSON-> Protobuf & back conversion



apache hbase download (6)

Tengo un sistema existente, que utiliza un protocolo de comunicación basado en protobuf entre la GUI y el servidor. Ahora me gustaría agregar algo de persistencia, pero en este momento los mensajes de protobuf se convierten directamente a objetos personalizados de terceros.

¿Hay una manera de convertir los mensajes de proto a json , que luego podrían persistir en la base de datos.

NB: No me gusta mucho la idea de escribir protobuf binario en la base de datos, ya que un día puede no ser compatible con versiones anteriores y romper el sistema de esa manera.


No me gusta mucho la idea de escribir protobuf binario en la base de datos, porque un día puede no ser compatible con versiones anteriores y romper el sistema de esa manera.

Es mucho más probable que la conversión de protobuf a JSON para el almacenamiento y luego de vuelta a protobuf en carga genere problemas de compatibilidad, porque:

  • Si el proceso que realiza la conversión no se construye con la última versión del esquema protobuf, la conversión eliminará silenciosamente los campos que el proceso no conoce. Esto es cierto tanto para los fines de almacenamiento como de carga.
  • Incluso con el esquema más reciente disponible, la conversión JSON <-> Protobuf puede tener pérdidas en presencia de valores de punto flotante imprecisos y casos de esquina similares.
  • Los protobufs en realidad tienen (ligeramente) más garantías de compatibilidad con versiones anteriores que JSON. Al igual que con JSON, si agrega un nuevo campo, los clientes antiguos lo ignorarán. A diferencia de JSON, Protobufs permite declarar un valor predeterminado, lo que puede hacer que sea algo más fácil para los nuevos clientes tratar con datos antiguos que de lo contrario no están en el campo. Esto es solo una pequeña ventaja, pero, por lo demás, Protobuf y JSON tienen propiedades equivalentes de compatibilidad con versiones anteriores, por lo tanto, no está obteniendo ninguna ventaja de compatibilidad con versiones anteriores al almacenar en JSON.

Con todo lo dicho, hay muchas bibliotecas por ahí para convertir protobufs a JSON, generalmente construidas en la interfaz de reflexión de Protobuf (no debe confundirse con la interfaz de reflexión de Java; la interfaz com.google.protobuf.Message ofrece la reflexión de Protobuf) .


Agregando a la respuesta de , JsonFormat está disponible incluso antes de protobuf 3.0. Sin embargo, la forma de hacerlo difiere un poco.

En Protobuf 3.0+, la clase JsonFormat es un singleton y, por lo tanto, hace algo como lo siguiente

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

En Protobuf 2.5+, lo siguiente debería funcionar

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

Aquí hay un enlace a un tutorial que escribí que usa la clase JsonFormat en un TypeAdapter que se puede registrar en un objeto GsonBuilder. Luego puede usar los métodos Gson toJson y fromJson para convertir los datos de proto a Java y viceversa.

En respuesta a jean . Si tenemos los datos de protobuf en un archivo y queremos analizarlos en un objeto de mensaje de protobuf, use el método de combinación de la clase TextFormat . Vea el siguiente fragmento de código:

// 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();



Para protobuf 2.5, usa la dependencia:

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

Luego usa el código:

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


Pruebe JsonFormat.printer().print(MessageOrBuilder) , se ve bien para proto3. Sin embargo, no está claro cómo convertir el mensaje protobuf real (que se proporciona como el paquete java de mi elección definido en el archivo .proto) en un objeto com.google.protbuf.Message.


Actualmente estamos utilizando el protobuf-java-format para convertir nuestros mensajes de Protobuf (cualquier subclase de Message ) a un formato JSON para enviar a través de nuestra API web.

Simplemente haz:

JsonFormat.printToString(protoMessage)