How to (de)serialize data using protobuf

First of all download, unzip and add these two dll files to your UserData/Plugins directory and restart OB2.

Protobuf.zip (264.6 KB)

Alternatively you can manually compile a project referencing this library GitHub - protobuf-net/protobuf-net: Protocol Buffers library for idiomatic .NET and you can get those two dll files as output.

After you did that, create a new config and switch to the LoliCode tab.
Click on Toggle Usings and add these two

ProtoBuf
System.IO

Finally paste this code in the LoliCode editor and run the config

// This is where we define the protobuf data structures
[ProtoContract]
class Person {
    [ProtoMember(1)]
    public int Id {get;set;}
    [ProtoMember(2)]
    public string Name {get;set;}
    [ProtoMember(3)]
    public Address Address {get;set;}
}
[ProtoContract]
class Address {
    [ProtoMember(1)]
    public string Line1 {get;set;}
    [ProtoMember(2)]
    public string Line2 {get;set;}
}

// This is where we create an instance of the above code and assign our values
var person = new Person
{
    Id = 12345,
    Name = "Fred",
    Address = new Address
    {
        Line1 = "Flat 1",
        Line2 = "The Meadows"
    }
};

// This will serialize the object to a byte array using the protobuf serialization
var ms = new MemoryStream();
Serializer.Serialize(ms, person);
var bytes = ms.ToArray();
ms.Dispose();

The code above will produce a variable called bytes that you can use when sending a request with raw content, for example

BLOCK:HttpRequest
  TYPE:RAW
  @bytes
  "application/protobuf"
ENDBLOCK

In order to produce the two classes that you see above starting from a .proto file you can use this online tool https://protogen.marcgravell.com/ (just go to the options and upload your .proto file, it will generate the C# code that you need to put insdead of the 2 sample classes that are in the snippet above).


To deserialize the response from the server you will need to create other classes with the model that you expect to receive from the server. After the HttpRequest block, you will have the response of the server in data.RAWSOURCE which we assume being another protobuf-serialized byte array.

Let’s simulate this by reassigning the same thing we already sent, just for testing

data.RAWSOURCE = bytes;

Now we need to instantiate a new object (in our example, of type Person) and deserialize the byte array to it.

Person receivedPerson;
var ms2 = new MemoryStream(data.RAWSOURCE);
receivedPerson = Serializer.Deserialize<Person>(ms2);
ms2.Dispose();

LOG receivedPerson.Name

The snippet above will successfully print Fred to the log. We can access the fields of this deserialized class through the usual C# syntax.

Ruri

10 Likes