Odpowiedź może być nieco spóźniona, ale może to nadal pomaga komuś.
W bieżącej wersji buforów protokołów 3 pack
i unpack
są available in Java.
W przykładzie pakowania można zrobić tak:
Any anyMessage = Any.pack(protoMess.build()));
i rozpakowywanie jak:
ProtoMess protoMess = anyMessage.unpack(ProtoMess.class);
Tutaj jest również pełny przykład do obsługi wiadomości protokołu buforów zagnieżdżonych Any
komunikatów:
ProtocolBuffers Files
prosty protokół Zderzaki złożyć zagnieżdżonego Any
wiadomości może wyglądać tak:
syntax = "proto3";
import "google/protobuf/any.proto";
message ParentMessage {
string text = 1;
google.protobuf.Any childMessage = 2;
}
Możliwym zagnieżdżony wiadomość może następnie być:
syntax = "proto3";
message ChildMessage {
string text = 1;
}
pakowania
Aby zbudować pełną wiadomość The można użyć następującej funkcji:
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();
}
Rozpakowanie
Aby odczytać wiadomość dziecko od wiadomości dominującej następująca funkcja może być używany:
public ChildMessage readChildMessage(ParentMessage parentMessage) {
try {
return parentMessage.getChildMessage().unpack(ChildMessage.class);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
EDIT:
Jeśli pakowanych wiadomości mogą mieć różne typy, można przeczytaj typeUrl
i użyj odbicia, aby rozpakować wiadomość.Zakładając, że masz wiadomości potomnych ChildMessage1
i ChildMessage2
można wykonać następujące czynności:
@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;
}
}
Dla dalszego przetwarzania, można określić typ wiadomości z instanceof
, co nie jest bardzo skuteczny. Jeśli chcesz otrzymać wiadomość pewnego typu, należy porównać typeUrl
bezpośrednio ze:
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;
}
}
Czy nie ma innego sposobu niż ten 'readChildMessage'? Co jeśli mam dziesiątki różnych wiadomości, które mogą wejść? Po prostu dodaj nowe blokowanie "try-catch"? Nawet 'switch-case' i podobne są absolutnie niedopuszczalne. – Sorona
Dobre pytanie, zapomniałem dodać, że można uzyskać nazwę upakowanej wiadomości jako 'typURL'. Pozwala to rozpakować dowolną wiadomość poprzez odbicie lub bezpośrednio zdecydować, co zrobić z wiadomością. Dodałem dwa przykłady do mojej odpowiedzi, mam nadzieję, że to pomoże. – sundance
Świetnie! Pomogło mi! – FisherCoder