1

Is there a way to serialize and then deserialize a class that has a member variable of unknown type that could be either be a simple value type or an instance of the containing class itself ?

public class A
{
    public dynamic Value { get; set; }//Value could be int or type A for example
}

public static class ASerializer
{
    public static string ToJson(A table)
    {
        return JsonConvert.SerializeObject(table);//using Json.Net
    }

    public static A FromJson(string json)
    {
        return JsonConvert.DeserializeObject<A>(json);
    }
}

public class Tests
{
    public static void TestASerialization()
    {
        var a = new A() { Value = 1 };
        var aa = new A { Value = a };
        var aaa = new A { Value = aa };
        var json = ASerializer.ToJson(aaa);
        var aaa2 = ASerializer.FromJson(json);

        var aa2 = (A)aaa2.Value;    //throws
    }
}

if I serialize and then deserialize aaa - I can't cast the Value of the deserialized aaa back to type A I get:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot convert type 'Newtonsoft.Json.Linq.JObject' to 'A'

Any suggestions on handling this nested hierarchy elegantly, without resorting to hand coding ? Seems to work with just one instance of A with Value of type A.

  • You can use [`TypeNameHandling`](http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm) to serialize polymorphic properties and retain the type after deserialization. – dbc Oct 12 '16 at 20:50
  • To apply `TypeNameHandling` to a specific property see [here](https://stackoverflow.com/questions/2254872/using-json-net-converters-to-deserialize-properties/6303853#6303853). – dbc Oct 12 '16 at 23:39
  • thanks, I did try this but obviously didn't implement it correctly using JsonSerializerSettings with property of TypeNameHandling = TypeNameHandling.All worked – Sample Player Oct 13 '16 at 09:13

2 Answers2

0

You aren't casting what you think you're casting.

In this case, you're actually casting the Value property to A. You need to wrap the aaa2 instance in params with the cast before accessing the property.

var aa2 = ((A)aaa2).Value; 
David L
  • 32,885
  • 8
  • 62
  • 93
0

Dynamic is a compiler hack mostly, I would recommend generics instead. @David L 's answer is also correct.

public class A<T>
{
    public T Value { get; set; }
}
Paul Swetz
  • 2,234
  • 1
  • 11
  • 28
  • how exactly can you restrict a generic to just a value type of int and the type A given ? – Sample Player Oct 13 '16 at 09:11
  • A something = new A(); something.Value = 1; //no problem something.Value = "";//exception – Paul Swetz Oct 13 '16 at 12:56
  • poor phrasing on my part, my actual requirement is for class A to hold a value that could be a value type or itself - and I want to prevent any other type to be used. In the actual implementation which I have not added above as it wasn't relevant to the serialization problem, I would restrict the possible range of types supported by use of overloaded constructors and accessor methods. Your example above would allow someone to create an instance of A that holds any type at all. – Sample Player Oct 13 '16 at 14:29