Die Antwort könnte ein bisschen spät sein, aber vielleicht hilft dies noch jemand.
In der aktuellen Version der Protokollpuffer 3 pack
und unpack
sind available in Java.
Any anyMessage = Any.pack(protoMess.build()));
und Auspacken wie:
ProtoMess protoMess = anyMessage.unpack(ProtoMess.class);
Hier ist auch ein vollständiges Beispiel für den Umgang mit Protocol Buffers Nachrichten mit verschachtelten Any
Nachrichten
In Ihrem Beispiel Verpackung kann wie geschehen:
ProtocolBuffers Dateien
Ein einfaches Protocol Buffers mit einer verschachtelten Any
Nachricht Datei aussehen könnte:
syntax = "proto3";
import "google/protobuf/any.proto";
message ParentMessage {
string text = 1;
google.protobuf.Any childMessage = 2;
}
Eine mögliche verschachtelte Nachricht könnte dann sein:
syntax = "proto3";
message ChildMessage {
string text = 1;
}
Verpackung
Um die vollständige Nachricht baut die Folgende Funktion kann verwendet werden:
public ParentMessage createMessage() {
// Create child message
ChildMessage.Builder childMessageBuilder = ChildMessage.newBuilder();
childMessageBuilder.setText("Child Text");
// Create parent message
ParentMessage.Builder parentMessageBuilder = ParentMessage.newBuilder();
parentMessageBuilder.setText("Parent Text");
parentMessageBuilder.setChildMessage(Any.pack(childMessageBuilder.build()));
// Return message
return parentMessageBuilder.build();
}
Auspacken
Um die Kinder Nachricht von der übergeordneten Nachricht die folgende Funktion verwendet werden kann, lesen:
public ChildMessage readChildMessage(ParentMessage parentMessage) {
try {
return parentMessage.getChildMessage().unpack(ChildMessage.class);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
EDIT:
Wenn Ihre gepackten Nachrichten verschiedene Typen haben, können Sie Lesen Sie die typeUrl
aus und verwenden Sie die Reflektion, um die Nachricht zu entpacken.Vorausgesetzt, dass Sie die Kindnachrichten haben ChildMessage1
und ChildMessage2
können Sie folgendes tun:
@SuppressWarnings("unchecked")
public Message readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
String clazzPackage = String.format("package.%s", clazzName);
Class<Message> clazz = (Class<Message>) Class.forName(clazzPackage);
return childMessage.unpack(clazz);
} catch (ClassNotFoundException | InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
Zur weiteren Verarbeitung können Sie die Art der Nachricht mit instanceof
bestimmen, die nicht sehr effizient ist. Wenn Sie eine Nachricht eines bestimmten Typs erhalten möchten, sollten Sie die typeUrl
direkt vergleichen:
public ChildMessage1 readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
if (clazzName.equals("ChildMessage1")) {
return childMessage.unpack("ChildMessage1.class");
}
return null
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
Gibt es keine andere Möglichkeit, als diese 'readChildMessage'? Was, wenn ich dutzende verschiedene Nachrichten habe, die reinkommen könnten? Fügen Sie einfach neue "try-catch" Blöcke hinzu? Selbst 'switch-case' und ähnliches ist absolut inakzeptabel. – Sorona
Gute Frage, ich habe vergessen hinzuzufügen, dass Sie den Namen der gepackten Nachricht als 'typeURL' erhalten können. Dies ermöglicht es, jede Nachricht per Reflexion auszupacken oder direkt zu entscheiden, was mit der Nachricht geschehen soll. Ich habe meiner Antwort zwei Beispiele hinzugefügt, ich hoffe, das hilft. – sundance
Großartig! Es hat mir geholfen! – FisherCoder