0

If I want to deserialize to an ExpandoObject using Json.NET, I can do the following:

var obj2 = JsonConvert.DeserializeObject<ExpandoObject>(serializedData, new ExpandoObjectConverter());

But because I need to get back an object with a certain interface out of deserialization, I need to use a DynamicObject instead of ExpandoObject:

   public interface ISomeInterface
    {
        public string InterfaceMember { get; set; }
    }

    public class SomeClass: ISomeInterface
    {
        public int X { get; set; }
        public string InterfaceMember { get; set; }
    }

    public class SomeClass2 : DynamicObject, ISomeInterface
    {
        public string InterfaceMember { get; set; }
    }

But when I do the following, I get an error:

       var obj = new SomeClass
        {
            InterfaceMember = "xyz",
            X = 3
        };

        string serializedData = JsonConvert.SerializeObject(obj);

        SomeClass2 obj2 = JsonConvert.DeserializeObject<SomeClass2>(serializedData, new ExpandoObjectConverter());

And the error is:

'SomeClass2' does not contain a definition for 'X'

How can I make it work for a DynamicObject?

NOTE: I am providing the concrete class SomeClass here just for the sake of the example. At runtime, it can actually be any type implementing ISomeInterface. So, I cannot deserialize directly to SomeClass. My actual goal is to deserialize to ISomeInterface.

4
  • Serializing to an arbitrary type implementing a certain interface still doesn't mandate using DynamicObject. You can just use the overload that takes a Type at runtime (providing the actual type, and casting to ISomeInterface afterwards). Commented Oct 2, 2019 at 12:59
  • 2
    It's because TryGetMember for X return false ... if you would override it (both TryGet/TrySet) then this would work Commented Oct 2, 2019 at 13:09
  • 1
    dotnetfiddle.net/0ml3L0 also SomeClass2 has no definition of X at compile time ... so obviosuly for variable of type SomeClass2 is not valid to ask about property X ... but for dynamic it is valid Commented Oct 2, 2019 at 13:15
  • @Selvin I tried your solution and it works for creating this dynamic object. But when I serialize it again, it creates an empty object: Console.WriteLine(JsonConvert.SerializeObject(t)); Commented Oct 2, 2019 at 14:37

1 Answer 1

2

The following code for SomeClass2 solves the problem (thanks to @Selvin's comment and sample fiddle):

public class SomeClass2 : DynamicObject, ISomeInterface
{
    private Dictionary<string, object> dictionary = new Dictionary<string, object>();

    [JsonProperty]
    public string InterfaceMember { get; set; }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return dictionary.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;
        return true;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return dictionary.Keys;
    }
}

I just added the GetDynamicMemberNamesoverride and added [JsonProperty] attribute to the InterfaceMember property so that reserializing the deserialized dynamic object will not be empty.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.