serdedotnet / serde

Serde.NET is a C# port of the popular Serde serialization library for Rust
https://serdedotnet.github.io/
BSD 3-Clause "New" or "Revised" License
142 stars 5 forks source link

How to deserialize a subtype using the type name given in the input data? #146

Closed nordyuki closed 8 months ago

nordyuki commented 9 months ago

Hi, I'm currently working on a project where I'm implementing a deserializer using Serde.NET. I have encountered a specific scenario and would appreciate some guidance on how to approach it.

Here is the simplified example of the scenario:

We first declare the following example types:

[GenerateDeserialize]
class Foo {
  public AbstractBar bar;
}

abstract class AbstractBar { }

[GenerateDeserialize]
class Bar1 : AbstractBar {
  public int bar;
}

[GenerateDeserialize]
class Bar2 : AbstractBar {
  public double bar;
}

And then, we extend the JSON encoding so that, if an object starts with a property "_t" (or whatever other type tagging, the details don't matter), the value of the property is the FQN of the type, so we can deserialize children class or interface implementations and assign them to the base class/interface.

For example, the following JSON input:

{ "bar": { "_t": "Bar1", "bar": 1234 } }

Would deserialize to the following data structure.

new Foo { bar = new Bar1 { bar = 1234 } }

I have noticed that there's IDeserializer::DeserializeType(typeName, fieldNames, v), but I can't find any detailed documentation or examples in this repository on how to use it (other than redirecting it into DeserializeDictionary). Could you please provide some guidance on implementing a feature like this in the deserializer?

agocke commented 8 months ago

Yeah the deserialize is more complicated. I’ll write up an example today

agocke commented 8 months ago

Added a sample: https://github.com/serdedotnet/serde/blob/main/samples/unions/Program.cs

A lot of the complexity is in the InlineDeserializer, which exists because the type tag and the data are in the same JSON object. I think if the subtypes were nested, this would be simpler to represent. I'm going to do some refactoring to try to make this simpler in the future.

nordyuki commented 8 months ago

That really helps! Thanks for the rapid response!