9 votes

Existe-t-il un moyen d'écrire des données proto sans générer de code ?

J'aimerais savoir s'il est possible d'utiliser l'API de réflexion fournie par google protobuf pour sérialiser des messages sans générer de code ?

La mémoire tampon du protocole nous permet d'utiliser la réflexion sur Message o Message.Builder objets après le processus d'analyse . Mais dans mon cas, j'aimerais savoir si je peux remplir ces objets avec des champs/valeurs, puis les écrire dans un fichier.

6voto

crazymaik Points 631

Flux de sortie codé

Une façon d'y parvenir est de comprendre comment une le message est encodé et utiliser le Flux de sortie codé pour écrire des champs de messages avec les write*() des méthodes.

Par exemple, pour écrire le message suivant :

message MyMessage {
    int foo = 1;
    string bar = 2;
}

Vous utiliserez ce morceau de code :

ByteArrayOutputStream baos = new ByteArrayOutputStream();
CodedOutputStream out = CodedOutputStream.newInstance(baos);
out.writeInt32(1, 1);
out.writeString(2, "s");
out.flush();
byte[] rawProtocolBuffer = baos.toByteArray();

Message dynamique

Une autre méthode consiste à créer les descripteurs à la main, puis à utiliser la fonction DynamicMessage pour définir les champs respectifs, mais c'est plus fastidieux que d'utiliser CodedOutputStream directement.

String messageName = "MyMessage";
FileDescriptorProto fileDescriptorProto = FileDescriptorProto
        .newBuilder()
        .addMessageType(DescriptorProto.newBuilder()
                .setName(messageName)
                .addField(FieldDescriptorProto.newBuilder()
                        .setName("foo")
                        .setNumber(1)
                        .setType(FieldDescriptorProto.Type.TYPE_INT32)
                        .build())
                .addField(FieldDescriptorProto.newBuilder()
                        .setName("bar")
                        .setNumber(2)
                        .setType(FieldDescriptorProto.Type.TYPE_STRING)
                        .build())
                .build())
        .build();

Descriptor messageDescriptor = FileDescriptor
        .buildFrom(fileDescriptorProto, new FileDescriptor[0])
        .findMessageTypeByName(messageName);

DynamicMessage message = DynamicMessage
        .newBuilder(messageDescriptor)
        .setField(messageDescriptor.findFieldByNumber(1), 1)
        .setField(messageDescriptor.findFieldByName("bar"), "s")
        .build();

byte[] rawProtocolBuffer = message.toByteArray();

1voto

Lahiru Chandima Points 5419

Il faut d'abord compiler le fichier proto en un fichier desc.

protoc --descriptor_set_out=point.desc --include_imports point.proto

Ensuite, utilisez le fichier desc pour encoder et décoder les messages.

InputStream input = new FileInputStream("point.desc");
DescriptorProtos.FileDescriptorSet descriptorSet = DescriptorProtos.FileDescriptorSet.parseFrom(input);
DescriptorProtos.FileDescriptorProto fileDescriptorProto = descriptorSet.getFile(0);

Descriptors.Descriptor messageDescriptor = Descriptors.FileDescriptor
        .buildFrom(fileDescriptorProto, new Descriptors.FileDescriptor[0])
        .findMessageTypeByName("Point");

// Encoding
DynamicMessage message = DynamicMessage
        .newBuilder(messageDescriptor)
        .setField(messageDescriptor.findFieldByNumber(1), 10)
        .setField(messageDescriptor.findFieldByNumber(2), 5)
        .setField(messageDescriptor.findFieldByName("label"), "test label")
        .build();

byte[] encodedBytes = message.toByteArray();

// Decoding
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(messageDescriptor, encodedBytes);

int x = (int) dynamicMessage.getField(messageDescriptor.findFieldByName("x"));
int y = (int) dynamicMessage.getField(messageDescriptor.findFieldByName("y"));
String label = (String) dynamicMessage.getField(messageDescriptor.findFieldByName("label"));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X