2012-07-20 9 views
7

Oto co próbuję dowiedzieć się, ich docs nie wyjaśniają to na tyle dobrze, przynajmniej dla mnie ..Jak przeanalizować wiadomość w klasie DynamicMessage, a następnie wykonać iterację za pomocą pól?

senario:

mam 5 plików proto że generują z protoc dla C++. Moja aplikacja musi otrzymać wiadomość, a następnie móc przeglądać wszystkie pola podczas uzyskiwania dostępu do ich wartości i nazw.

Co chcę zrobić, to przetworzyć wiadomość w klasie DynamicMessage, a następnie wykonać iterację za pomocą pól. W ten sposób nie muszę dokładnie wiedzieć, jaki to jest komunikat i mogę obsłużyć je wszystkie w jeden ogólny sposób.

Wiem, że można obsłużyć wiadomości, parsując je do ich określonego typu, a następnie traktując je jako swoją klasę wiadomości, ale dla mojej aplikacji, która nie jest pożądana.

Wygląda na to, że to, co chcę zrobić, powinno być możliwe za pośrednictwem klasy "--descriptor_set_out" i klasy dynamicznej.

Co Próbowałem (I nie powiodło się z):

przeniosłem descriptor.proto do folderu z moich PROTOS i włączyła ją wzdłuż boku moich innych na etapie kompilacji. Ustawiłem również opcję - descriptor_set_out, aby drukować do pliku "my_descriptors.pb.ds" Nie mam pojęcia, skąd dalej.

Here's what i've referenced, although there isn't much... Przepraszamy za długi wpis i nieco niejasny schemat nazewnictwa tematów.

Ponadto, jeśli nie było to jasne, zakładam, że wiadomości nie są "nieznane". Zakładam, że nadal będzie wymagane uwzględnienie odpowiednich nagłówków dla każdego proto, więc mój kod wie o "nieznanym" komunikacie.

+1

Jedno pytanie - dlaczego chcesz to zrobić? jeśli przenosisz opis komunikatu (nazwy i typy - które są wymagane, aby móc dokonywać iteracji po nazwach pól) wraz z samą wiadomością, zasadniczo anulujesz premie wydajności i wielkości nieautomatycznego opisu wiadomość (która jest protobuf). Możesz po prostu użyć JSON-a do tego. – DarkWanderer

+0

@DarkWander, moim użyciem było to, że mam binarny komunikat dla celów efektywności, który przepływa przez niektóre procesy subowe pubu. Mam inny proces, który chciałem usiąść i posłuchać wszystkich wiadomości przepływających przez proces subdarzenia. Może zawierać wszystkie potrzebne nagłówki do dekodowania komunikatów, a następnie wyprowadzać je w czytelnym łańcuchu KeyValue do pliku dziennika w celu audytu/debugowania. Nie chciałbym pisać dekodera/tłumacza dla każdego nowego typu dodawanego przeze mnie. Chciałbym po prostu zrzucić bajty do poprawnego typu i powtarzać pola w sposób ogólny. – bgura

Odpowiedz

0

Najpopularniejszym sposobem jest użycie kompozycji wiadomości. Coś jak:

message Foo {...} 
message Bar {...} 
message GenericMessage { 
    enum Type {FOO = 1, BAR = 2}; 
    optional Foo foo = 1; 
    optional Bar bar = 2; 
} 

Jeśli upewnij się, że dokładnie jedna z obu Foo lub Bar jest obecny w każdym GenericMessage, można uzyskać pożądane zachowanie. Czytasz jeden GenericMessage, a następnie przetwarzasz go jako jedną z kilku określonych wiadomości.

Pomyśl o refaktoryzacji protokołu. Jeśli wszystko, co musisz zrobić, to iteracyjne nad polami, może byłbyś lepiej coś jak zwykły klucz-wartość mapie:

message ValueMessage { 
    required string key = 1; 
    optional int IntValue = 2; 
    optional string StringValue = 3; 
    optional bool BoolValue = 4; 
    ... 
} 
message GenericMessage{ 
    repeated ValueMessage = 1; 
} 

Albo można byłaby protokół, który w jakiś inny sposób.

0

Ostrzeżenie: Moja odpowiedź nie jest całkowicie poprawna Mam pewne błędy kompilacji dotyczące konfliktów, będę edytować, gdy to naprawię :). ale to jest punkt wyjścia

Może minęło dużo czasu, odkąd to pytanie zostało opublikowane, ale miałem teraz do czynienia z czymś podobnym w obecnych czasach z buforami protokołów.

Przede wszystkim odniesienia jest niewłaściwy opcja na polecenia, które należy dodać to:

--descriptor_set_out=<Directory>

gdzie Directory gdzie jest kompilowany wersja descriptor.proto (lub .proto skompilowany, który opisuje plik) jest usytuowany.

po tym będziemy musieli dodać odniesienie do pliku Descriptor.proto w pliku .proto autodescriving.

message MyMessage 
{ 
    required google.protobuf.FileDescriptorSet proto_files = 1; 
    ... 
} 
+0

Brak tego kroku polega na poślubieniu odwołania DescriptorProto do komunikatu DynamicMessage. Jest luźno omawiana tutaj na https://developers.google.com/protocol-buffers/docs/techniques#self-description bez przykładów :( –

Powiązane problemy