This is a late answer, but I had the same problem, and this question helped me solve them.
As a summary, I thought I should post my results, in hopes that it speeds up the implementation for others.
First the ExpandoJsonResult, which you can return an instance of in your action. Or you can override the Json method in your controller and return it there.
public class ExpandoJsonResult : JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
response.ContentEncoding = ContentEncoding ?? response.ContentEncoding;
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoConverter() });
response.Write(serializer.Serialize(Data));
}
}
}
Then the converter (which supports both serialization and de-serialization. See below for an example of how to de-serialize).
public class ExpandoConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{ return DictionaryToExpando(dictionary); }
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{ return ((ExpandoObject)obj).ToDictionary(x => x.Key, x => x.Value); }
public override IEnumerable<Type> SupportedTypes
{ get { return new ReadOnlyCollection<Type>(new Type[] { typeof(System.Dynamic.ExpandoObject) }); } }
private ExpandoObject DictionaryToExpando(IDictionary<string, object> source)
{
var expandoObject = new ExpandoObject();
var expandoDictionary = (IDictionary<string, object>)expandoObject;
foreach (var kvp in source)
{
if (kvp.Value is IDictionary<string, object>) expandoDictionary.Add(kvp.Key, DictionaryToExpando((IDictionary<string, object>)kvp.Value));
else if (kvp.Value is ICollection)
{
var valueList = new List<object>();
foreach (var value in (ICollection)kvp.Value)
{
if (value is IDictionary<string, object>) valueList.Add(DictionaryToExpando((IDictionary<string, object>)value));
else valueList.Add(value);
}
expandoDictionary.Add(kvp.Key, valueList);
}
else expandoDictionary.Add(kvp.Key, kvp.Value);
}
return expandoObject;
}
}
You can see in the ExpandoJsonResult class how to use it for serialization. To de-serialize, create the serializer and register the converter in the same way, but use
dynamic _data = serializer.Deserialize<ExpandoObject>("Your JSON string");
A big thank you, to all participants here that helped me.