I have a little test class like so :
public class Command
{
public dynamic MyData { get; set; }
}
As the dynamic MyData
I want to use ExpandoObject, so I can do:
Command cmd = new Command();
cmd.MyData = new ExpandoObject();
cmd.MyData.SomeStuff = 4;
cmd.MyData.SomeOtherStuff = "hi";
I am trying to serialize to/deserialize from json. To do this I am using JavaScriptSerializer
.
I want an example object above to serialize to:
{
MyData : {
SomeStuff : 4,
SomeOtherStuff : "hi"
}
}
To do this I need a JavaScriptConverter
(taken from this website):
public class ExpandoJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return dictionary.ToExpando();
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var result = new Dictionary<string, object>();
var dictionary = obj as IDictionary<string, object>;
foreach (var item in dictionary)
result.Add(item.Key, item.Value);
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new Type[] { typeof(ExpandoObject) });
}
}
}
public static class IDictionaryExtensions {
/// <summary>
/// Extension method that turns a dictionary of string and object to an ExpandoObject
/// Snagged from http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
/// </summary>
public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary) {
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;
// go through the items in the dictionary and copy over the key value pairs)
foreach (var kvp in dictionary) {
// if the value can also be turned into an ExpandoObject, then do it!
if (kvp.Value is IDictionary<string, object>) {
var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key, expandoValue);
}
else if (kvp.Value is ICollection) {
// iterate through the collection and convert any strin-object dictionaries
// along the way into expando objects
var itemList = new List<object>();
foreach (var item in (ICollection)kvp.Value) {
if (item is IDictionary<string, object>) {
var expandoItem = ((IDictionary<string, object>)item).ToExpando();
itemList.Add(expandoItem);
}
else {
itemList.Add(item);
}
}
expandoDic.Add(kvp.Key, itemList);
}
else {
expandoDic.Add(kvp);
}
}
return expando;
}
}
Now this works neat for serializing, but there is a following problem with deserializing:
- since
MyData
is adynamic
object, and theExpandoJsonConverter
expects ExpandoObject, the data deserialized toMyData
is of typeIDictionary<string, object>
. - if I change
dynamic MyData
to beExpandoObject MyData
, I won't be able to saycmd.MyData.SomeStuff = 4;
, the compiler will tell me that "ExpandoObject does not have property named SomeStuff". - finally, I could add
dynamic
to the list of supported types ofExpandoJsonConverter
, byt wait, you cant dotypeof(dynamic)
.
Is anyone aware of a neat workaround? I would really like this functionality, but I can't use 3rd party serialization libraries like Newtonsoft. Thanks.