Matías Fidemraizer Matías Fidemraizer - 20 days ago 6
C# Question

JSON.NET deserializes an object implementing IDictionary<TKey, TValue> as dictionary, how to force regular class serialization?

Let's say I've defined an

interface
:

public interface IExtensibleObject : IDictionary<string, object>
{
// Some members here, but it doesn't matter for this question
}


And I've designed a class which implements the whole interface:

public class Customer : IExtensibleObject
{
public Guid Id { get; set; }

// IExtensibleObject implemented members
}


When I try to deserialize a JSON
string
to
Customer
, JSON.NET will access the
IDictionary<TKey, TValue>
indexer to set
Id
property (i.e.
instance["Id"] = value
):

Customer customer = JsonConvert.DeserializeObject<Customer>(@"{""Id"":""bcf66a92-00ea-4124-afa7-a6c200ae5886""}");


Is there some built-in way of avoiding the whole behavior?. I need to deserialize the whole object as a regular object even when it implements
IDictionary<TKey, TValue>
.

Evk Evk
Answer

You can do it with custom contract resolver. Default contract resolver checks if class implements IDictionary and if so - serializes\deserializes it as such. You can change that:

class CustomResolver : DefaultContractResolver {
    protected override JsonContract CreateContract(Type objectType) {
        // if type implements your interface - serialize it as object
        if (objectType.GetInterfaces().Any(c => c == typeof(IExtensibleObject))) {
            return base.CreateObjectContract(objectType);
        }

        return base.CreateContract(objectType);
    }
}

And then just:

 var settings = new JsonSerializerSettings(); // or change default settings
 settings.ContractResolver = new CustomResolver();                        
 Customer customer = JsonConvert.DeserializeObject<Customer>(@"{""Id"":""bcf66a92-00ea-4124-afa7-a6c200ae5886""}", settings);