Protobuf C# не может десериализовать сообщение из protobufjs

Я пытаюсь десериализовать сообщение, которое публикуется скриптом на определенном веб-сайте. Я просмотрел скрипт и заметил, что он использует protobufjs. Структура сообщения загружается из файла JSON с сервера, который выглядит следующим образом:

{
"nested":{
    "InteractionCollection":{
        "fields":{
            "interactions":{
                "rule":"repeated",
                "type":"Interaction",
                "id":1
            },
            "mouseMovements":{
            "rule":"repeated",
                "type":"MouseMovement",
                "id":2
            },
            "url":{
                "type":"string",
                "id":3
            },
            "flags":{
                "rule":"repeated",
                "type":"Flag",
                "id":4
            }
        },
        "nested":{
            "Interaction":{
                "fields":{
                    "type":{
                        "type":"string",
                        "id":1
                    },
                    "time":{
                        "type":"int64",
                        "id":2
                    },
                    "elementId":{
                        "type":"string",
                        "id":3
                    },
                    "elementType":{
                        "type":"string",
                        "id":4
                    },
                    "additionalInfo":{
                        "type":"string",
                        "id":5
                    }
                }
            },
            "MouseMovement":{
                "fields":{
                    "time":{
                        "type":"int64",
                        "id":1
                    },
                    "x":{
                        "type":"int64",
                        "id":2
                    },
                    "y":{
                        "type":"int64",
                        "id":3
                    },
                    "wx":{
                        "type":"int64",
                        "id":4
                    },
                    "wy":{
                        "type":"int64",
                        "id":5
                    }
                }
            },
            "Flag":{
                "fields":{
                    "time":{
                        "type":"int64",
                        "id":1
                    },
                    "name":{
                        "type":"string",
                        "id":2
                    }
                }
            }
        }
    }
}

Затем он создает новый экземпляр сообщения "InteractionCollection" и помещает в него новые взаимодействия, mouseMovements и флаги.

instance = message.create({
    url : "someurl",
    interactions : [],
    mouseMovements : []
})

var some_interaction = interaction_message.create({
    time : Date.now(),
    elementId : "idstring",
    elementType : "typestring",
    type : "anotherstring",
    additionalInfo : "infostring"
});
instance.interactions.push(some_interaction);

В конце сценария он отправляет данные в сериализованном формате на сервер следующим образом:

navigator.sendBeacon("someserverpath", message.encode(instance).finish());

Я работаю с C#, поэтому я установил официальный Buffer Package протокола Google через NuGet (Google.Protobuf) и создал файл proto для репликации дескриптора json сверху:

syntax = "proto3";
option csharp_namespace = "Proto2"; //C# Project Name: Proto2

message InteractionCollection {
    repeated Interaction interactions = 1;
    repeated MouseMovement mouse_movements = 2;
    string url = 3;
    repeated Flag flags = 4;

    message Flag {
        int64 time = 1;
        string name = 2;
    }

    message Interaction {
        string type = 1;
        int64 time = 2;
        string element_id = 3;
        string element_type = 4;
        string additional_info = 5;
    }

    message MouseMovement {
        int64 time = 1;
        int64 x = 2;
        int64 y = 3;
        int64 wx = 4;
        int64 wy = 5;
    }
}

Затем я скомпилировал файл proto с использованием protoc.exe, который поставляется с пакетом NuGet, и включил полученный класс в мой проект. Затем я создал тест InteractionCollection и сериализовал его:

InteractionCollection collection = new InteractionCollection
{
    Url = "/",
    Interactions = {
    new Interaction{ Time = 1508602241363, ElementId = "DOM", ElementType = "DOM", Type = "tohru", AdditionalInfo = "" },
    new Interaction{ Time = 1508602243075, Type = "focus", AdditionalInfo = "" },
    },
};
using (var output = File.Create("csharp_out.dat"))
{
    collection.WriteTo(output);
}

И на сайте он сериализовал точно такое же Сообщение.

{
"interactions":[
    {"type":"tohru","time":"1508602241363","elementId":"DOM","elementType":"DOM","additionalInfo":""},
    {"type":"focus","time":"1508602243075","additionalInfo":""}
],
"url":"/"
}

Однако данные, которые я получаю из своего проекта на C#, немного отличаются от данных, размещаемых на веб-сайте. Мой файл протока неверен или есть другая причина для этого. Очевидно, это означает, что я также не могу десериализовать данные с сайта. C#:

tohruÓÂÍýó+DOM"DOM

focusƒÐÍýó+/

или же

\x0A\x18\x0A\x05\x74\x6F\x68\x72\x75\x10\xC3\x93\xC3\x82\xC3\x8D\xC3\xBD\xC3\xB3\x2B\x1A\x03\x44\x4F\x4D\x22\x03\x44\x4F\x4D\x0A\x0E\x0A\x05\x66\x6F\x63\x75\x73\x10\xC6\x92\xC3\x90\xC3\x8D\xC3\xBD\xC3\xB3\x2B\x1A\x01\x2F

JS:

tohruÓÂÍýó+DOM"DOM*

focusÐÍýó+*/

или же

\x1A\x0A\x05\x74\x6F\x68\x72\x75\x10\xC3\x93\xC3\x82\xC3\x8D\xC3\xBD\xC3\xB3\x2B\x1A\x03\x44\x4F\x4D\x22\x03\x44\x4F\x4D\x2A\x0A\x10\x0A\x05\x66\x6F\x63\x75\x73\x10\xC2\x83\xC3\x90\xC3\x8D\xC3\xBD\xC3\xB3\x2B\x2A\x1A\x01\x2F

Мне жаль, что это такой длинный вопрос, но я возился с ним больше недели, и я действительно не могу понять, в чем проблема. Спасибо за ваше терпение!

ОБНОВИТЬ:

После некоторого тестирования, выполняя protobufjs локально, я заметил, что версия Protobuf на C# интерпретирует пустую строку как ноль и, следовательно, оставляет все поле незаполненным (например, когда вы опускаете необязательное поле), тогда как protobufjs сериализует его для:

\x12\x00

Я также попробовал тот же тест с protobuf-net вместо версии Google, и он сериализовал пустую строку в:

\x12\x20

Есть ли способ изменить это поведение на тот, который использует protobufjs?

0 ответов

Другие вопросы по тегам