Is there a way to deserialize JSON content into a C# 4 dynamic type? It would be nice to skip creating a bunch of classes in order to use the DataContractJsonSerializer.
A:
For that I would use JSON.NET to do the low-level parsing of the JSON stream and then build up the object hierarchy out of instances of the ExpandoObject
class.
Daniel Earwicker
2010-06-29 16:07:38
+3
A:
Nikhil Kothari blogged about doing this. He included a link to his library which provides a dynamic implementation of a REST client, which works on JSON data. He also has a JSON client that works off strings of JSON data directly.
Reed Copsey
2010-06-29 16:08:39
Surely there is an implementation using only the built in datacontractjsonserializer. It'd be great to avoid a third party assembly reference
Joel Martinez
2010-09-21 13:05:55
Unfortunately that library doesn't work with .NET 4 RTM.
Drew Noakes
2010-09-27 12:56:46
+2
A:
Unfortunately the blog post by Nikhil Kothari doesn't work with .NET 4 RTM.
An alternative deserialisation approach is suggested here. I modified the code slightly to fix a bug and suit my coding style. All you need is this:
public class DynamicJsonObject : DynamicObject
{
private IDictionary<string, object> Dictionary { get; set; }
public DynamicJsonObject(IDictionary<string, object> dictionary)
{
Dictionary = dictionary;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!Dictionary.TryGetValue(binder.Name, out result))
return false;
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
{
result = new DynamicJsonObject(dictionary);
return true;
}
var arrayList = result as ArrayList;
if (arrayList != null && arrayList.Count > 0)
{
if (arrayList[0] is IDictionary<string, object>)
result = new List<DynamicJsonObject>(arrayList.ToArray().Select(x => new DynamicJsonObject(x as IDictionary<string, object>)));
else
result = new List<object>(arrayList.Cast<object>());
}
return true;
}
}
public class DynamicJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return type == typeof (object) ? new DynamicJsonObject(dictionary) : null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
}
}
You can use it like this:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
I'm interested in any discussion about this approach.
Drew Noakes
2010-09-27 17:46:10