Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize list of interface types with ServiceStack.Text

I'm looking at ways to introduce something other than BinaryFormatter serialization into my app to eventually work with Redis. ServiceStack JSON is what I would like to use, but can it do what I need with interfaces? It can serialize (by inserting custom __type attribute)

public IAsset Content;

but not

public List<IAsset> Contents;

- the list comes up empty in serialized data. Is there any way to do this - serialize a list of interface types?

The app is big and old and the shape of objects it uses is probably not going to be allowed to change. Thanks

like image 993
lokki Avatar asked Nov 12 '22 15:11

lokki


1 Answers

Quoting from http://www.servicestack.net/docs/framework/release-notes

You probably don't have to do much :)

The JSON and JSV Text serializers now support serializing and deserializing DTOs with Interface / Abstract or object types. Amongst other things, this allows you to have an IInterface property which when serialized will include its concrete type information in a __type property field (similar to other JSON serializers) which when serialized populates an instance of that concrete type (provided it exists).

[...]

Note: This feature is automatically added to all Abstract/Interface/Object types, i.e. you don't need to include any [KnownType] attributes to take advantage of it.

By not much:

public interface IAsset
{
    string Bling { get; set; }
}

public class AAsset : IAsset
{
    public string Bling { get; set; }
    public override string ToString()
    {
        return "A" + Bling;
    }
}

public class BAsset : IAsset
{
    public string Bling { get; set; }
    public override string ToString()
    {
        return "B" + Bling;
    }
}

public class AssetBag
{
    [JsonProperty(TypeNameHandling = TypeNameHandling.None)]
    public List<IAsset> Assets { get; set; } 
}

class Program
{


    static void Main(string[] args)
    {
        try
        {
            var bag = new AssetBag
                {
                    Assets = new List<IAsset> {new AAsset {Bling = "Oho"}, new BAsset() {Bling = "Aha"}}
                };
            string json = JsonConvert.SerializeObject(bag, new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.Auto
            });
            var anotherBag = JsonConvert.DeserializeObject<AssetBag>(json, new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.Auto
            });
like image 182
Hylaean Avatar answered Nov 15 '22 06:11

Hylaean