Saturday, September 26, 2015
How to only Serialize Interface Properties with Json.NET
When you serialize an object with Newtonsoft's Json.NET it will resolve the serialization contract for the type being serialized. This means that if you want to serialize an object so that it matches one of the interfaces that it implements you will need to use a customized contract resolver.
When I first tried to do this I made a completely custom JsonConverter for the type that looked up the properties via reflection and just wrote their values out manually. Unfortunately had the side effect of bypassing all of the features the Newtonsoft provides with regard to decorating classes and customizing the serialization process for that object.
There was a good topic on Stack Overflow about this that led me to the custom contract resolver solution. However the sample implementation there is hard coded to only try to serialize one hard coded type for all serialization.
Below is an implementation (with tests) that allows you to specify a list of interfaces that you want to serialize by, and then if the object being serialized does implement that interface it will fall back on it's default contract.
InterfaceContractResolver Implementation
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type[] _interfaceTypes;
private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
public InterfaceContractResolver(params Type[] interfaceTypes)
{
_interfaceTypes = interfaceTypes;
_typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var typeToSerialize = _typeToSerializeMap.GetOrAdd(
type,
t => _interfaceTypes.FirstOrDefault(
it => it.IsAssignableFrom(t)) ?? t);
return base.CreateProperties(typeToSerialize, memberSerialization);
}
}
Sunday, April 6, 2014
Deserialize Abstract Classes with Json.NET
Here is a fun problem: how do you deserialize an array of objects with different types, but all of which inherit from the same super class?
If you are using Newtonsoft's Json.NET, then this is actually rather easy to implement!
Example
Here are three classes...
public abstract class Pet { public string Name { get; set; } }
public class Dog : Pet { public string FavoriteToy { get; set; } }
public class Cat : Pet { public bool WantsToKillYou { get; set; } }
...here is an array with instances of those objects mixed together...
new Pet[]
{
new Cat { Name = "Sql", WantsToKillYou = true },
new Cat { Name = "Linq", WantsToKillYou = false },
new Dog { Name = "Taboo", FavoriteToy = "Sql" }
}
...and now let's make it serialize and deseriailze! :)
Extending the JsonConverter
This tactic is actually quite simple! You need to extend a JsonConverter for your specific super class that is able to somehow uniquely identify each child class. In this example we look for a specific property that only exists on the child class, and Newtonsoft's JObjects and JTokens make this very easy to do!
Saturday, February 8, 2014
Deserialize to ExpandoObject with Json.NET
I absolutely love Json.NET!
What I don't like is calling the non-generic DeserializeObject method and then having to deal with JToken wrappers. While these objects can be useful, I almost always want to just work directly with the data.
Good news, everyone! Newtonsoft natively supports deserializing to an ExpandoObject!
For anyone who does not know, ExpandoObjects are what .NET uses to let you create your own dynamic objects whose members can be dynamically added and removed at run time. The following two lines of code are ALL that you need to deserialize straight to an ExpandObjects:
var converter = new ExpandoObjectConverter();
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);
So why is this useful? To find out, let's take a look at some unit tests!