Java: JSON -> Protobuf & back conversion

J’ai un système existant, qui utilise un protocole de communication basé sur Protobuf entre l’interface graphique et le serveur. Maintenant, je voudrais append de la persistance, mais pour le moment, les messages protobuf sont directement convertis en objects personnalisés tiers.

Existe-t-il un moyen de convertir les messages proto en json , qui pourraient ensuite être conservés dans la firebase database.

NB: Je n’aime pas trop l’idée d’écrire protobuf binary dans une firebase database, car il pourrait un jour devenir rétro-compatible avec les versions les plus récentes et casser le système de cette façon.

Nous utilisons actuellement le format protobuf-java pour convertir nos messages Protobuf (toute sous-classe de Message ) en un format JSON à envoyer via notre API Web.

Simplement faire:

  JsonFormat.printToSsortingng(protoMessage) 

Je n’aime pas beaucoup l’idée d’écrire protobuf binary dans une firebase database, car il pourrait un jour devenir non compatible avec les versions plus récentes et casser le système de cette façon.

La conversion de protobuf en JSON pour le stockage, puis de nouveau en protobuf au chargement est beaucoup plus susceptible de créer des problèmes de compatibilité, pour les raisons suivantes:

  • Si le processus qui effectue la conversion n’est pas construit avec la dernière version du schéma protobuf, la conversion supprime automatiquement les champs inconnus du processus. Cela est vrai à la fois pour le stockage et le chargement.
  • Même avec le schéma le plus récent disponible, la conversion JSON <-> Protobuf peut entraîner des pertes en présence de valeurs à virgule flottante imprécises et de cas angulars similaires.
  • Les protobufs ont en fait des garanties de compatibilité ascendante (légèrement) plus fortes que JSON. Comme avec JSON, si vous ajoutez un nouveau champ, les anciens clients l’ignoreront. Contrairement à JSON, les Protobufs permettent de déclarer une valeur par défaut, ce qui peut aider les nouveaux clients à gérer plus facilement les anciennes données pour lesquelles le champ manque. Il ne s’agit que d’un léger avantage, mais sinon Protobuf et JSON ont des propriétés de compatibilité ascendante équivalentes. Par conséquent, vous ne gagnez aucun avantage en termes de compatibilité ascendante grâce au stockage dans JSON.

Cela dit, il existe de nombreuses bibliothèques pour convertir les protobufs en JSON, généralement construites sur l’interface de reflection Protobuf (à ne pas confondre avec l’interface de reflection Java; .

Comme mentionné dans une réponse à une question similaire , depuis la version 3.1.0, il s’agit d’une fonctionnalité prise en charge de ProtocolBuffers. Pour Java, incluez le module d’extension com.google.protobuf: protobuf-java-util et utilisez JsonFormat comme suit :

 JsonFormat.parser().ignoringUnknownFields().merge(json, yourObjectBuilder); YourObject value = yourObjectBuilder.build(); 

Ajoutant à la réponse d’ Ophir , JsonFormat est disponible avant même la version 3.0 de Protobuf. Cependant, la façon de le faire diffère un peu.

Dans Protobuf 3.0+, la classe JsonFormat est un singleton et fait donc quelque chose comme ci-dessous.

 Ssortingng jsonSsortingng = ""; JsonFormat.parser().ignoringUnknownFields().merge(json,yourObjectBuilder); 

Dans Protobuf 2.5+, ce qui suit devrait fonctionner

 Ssortingng jsonSsortingng = ""; JsonFormat jsonFormat = new JsonFormat(); jsonSsortingng = jsonFormat.printToSsortingng(yourProtobufMessage); 

Voici un lien vers un tutoriel que j’ai écrit qui utilise la classe JsonFormat dans un TypeAdapter pouvant être enregistré dans un object GsonBuilder. Vous pouvez ensuite utiliser les méthodes toJson et fromJson de Gson pour convertir les données proto en Java et inversement.

Répondre à Jean . Si nous avons les données protobuf dans un fichier et que nous souhaitons les parsingr dans un object de message protobuf, utilisez la méthode de fusion TextFormat, classe. Voir l’extrait ci-dessous:

 // Let your proto text data be in a file MessageDataAsProto.prototxt // Read it into ssortingng Ssortingng protoDataAsSsortingng = FileUtils.readFileToSsortingng(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(protoDataAsSsortingng, ExtensionRegistry.getEmptyRegistry(), myMsgBuilder); // Build the message and return return myMsgBuilder.build(); 

Essayez JsonFormat.printer().print(MessageOrBuilder) , ça a l’air bien pour proto3. Cependant, il est difficile de savoir comment convertir le message protobuf réel (fourni en tant que package Java de mon choix défini dans le fichier .proto) dans un object com.google.protbuf.Message.

Pour protobuf 2.5, utilisez la dépendance:

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

Ensuite, utilisez le code:

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