microsoft / bond

Bond is a cross-platform framework for working with schematized data. It supports cross-language de/serialization and powerful generic mechanisms for efficiently manipulating data. Bond is broadly used at Microsoft in high scale services.
MIT License
2.61k stars 321 forks source link

[C#] Deserializing bond-like strings into dynamic type #1184

Closed enzoferraribf closed 1 year ago

enzoferraribf commented 1 year ago

I'm trying to deserialize a bond-like string structure into a C# dynamic type, something like:

var schema = @"
    struct Person {
        0: string Name;
    }
";

var byteArray = Encoding.UTF8.GetBytes(schema);

var inputBuffer = new InputBuffer(byteArray);

var reader = new FastBinaryReader<InputBuffer>(inputBuffer);

var @object = Deserialize<dynamic>.From(reader);

Console.WriteLine(@object);

Failing with:

An unhandled exception of type 'System.IO.InvalidDataException' occurred in Bond.dll: 'Invalid BondDataType 32'

What is the correct way to do these kind of deserializations?

chwarr commented 1 year ago

I'm not entirely sure what you are trying to do. In your example, what members and values do you expect @object to have?

Right now, the schema string is a snippet of the Bond interface definition language. The code then "coerces" this into a FastBinary payload. This is not a valid FastBinary payload.


Focusing on just Deserialize<dynamic>.From(reader), no, Bond does not support deserializing into dynamic objects out-of-the-box. You need to deserialize into a object with a known, fixed schema.

To handle arbitrary, unknown schemas one option is to move down a layer and use the protocol readers directly. See for example, issue #1162 "In C# implementation, how to parse to structs separated by BT_STOP_BASE", and issue #1163 "Correct way to read list of mapped values in C#" for examples of someone else processing payloads via readers. Tagged payloads like FastBinary do not include field names. You'll need to get that information from another source, like a SchemaDef that exactly matches the payload when it was created.

Another option would be to implement an algorithm similar to what's in DeserializerTransform but that has a target of a dynamic object. Note: DeserializerTransform isn't a public API, so you'll need to duplicate much of the code if you take this approach.


Related: issue #585, "Deserialize objects with incomplete or inexisting type information"

chwarr commented 1 year ago

Let me know if you have any follow up questions or additional details. I'm going to close this issue for now.