Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize JSON into C# dynamic object?

Is there a way to deserialize JSON content into a C# dynamic type? It would be nice to skip creating a bunch of classes in order to use the DataContractJsonSerializer.

like image 346
jswanson Avatar asked Jun 29 '10 16:06

jswanson


People also ask

How do I deserialize JSON?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.

How do you serialize and deserialize an object in C# using JSON?

It returns JSON data in string format. In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom . Net object. In the following code, it calls the static method DeserializeObject() of the JsonConvert class by passing JSON data.


2 Answers

It's pretty simple using Json.NET:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");  string name = stuff.Name; string address = stuff.Address.City; 

Also using Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");  string name = stuff.Name; string address = stuff.Address.City; 

Documentation: Querying JSON with dynamic

like image 32
Tom Peplow Avatar answered Sep 29 '22 08:09

Tom Peplow


If you are happy to have a dependency upon the System.Web.Helpers assembly, then you can use the Json class:

dynamic data = Json.Decode(json); 

It is included with the MVC framework as an additional download to the .NET 4 framework. Be sure to give Vlad an upvote if that's helpful! However if you cannot assume the client environment includes this DLL, then read on.


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 code and a reference to System.Web.Extensions from your project:

using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using System.Linq; using System.Text; using System.Web.Script.Serialization;  public sealed 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) })); }     }      #region Nested type: DynamicJsonObject      private sealed class DynamicJsonObject : DynamicObject     {         private readonly IDictionary<string, object> _dictionary;          public DynamicJsonObject(IDictionary<string, object> dictionary)         {             if (dictionary == null)                 throw new ArgumentNullException("dictionary");             _dictionary = dictionary;         }          public override string ToString()         {             var sb = new StringBuilder("{");             ToString(sb);             return sb.ToString();         }          private void ToString(StringBuilder sb)         {             var firstInDictionary = true;             foreach (var pair in _dictionary)             {                 if (!firstInDictionary)                     sb.Append(",");                 firstInDictionary = false;                 var value = pair.Value;                 var name = pair.Key;                 if (value is string)                 {                     sb.AppendFormat("{0}:\"{1}\"", name, value);                 }                 else if (value is IDictionary<string, object>)                 {                     new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);                 }                 else if (value is ArrayList)                 {                     sb.Append(name + ":[");                     var firstInArray = true;                     foreach (var arrayValue in (ArrayList)value)                     {                         if (!firstInArray)                             sb.Append(",");                         firstInArray = false;                         if (arrayValue is IDictionary<string, object>)                             new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);                         else if (arrayValue is string)                             sb.AppendFormat("\"{0}\"", arrayValue);                         else                             sb.AppendFormat("{0}", arrayValue);                      }                     sb.Append("]");                 }                 else                 {                     sb.AppendFormat("{0}:{1}", name, value);                 }             }             sb.Append("}");         }          public override bool TryGetMember(GetMemberBinder binder, out object result)         {             if (!_dictionary.TryGetValue(binder.Name, out result))             {                 // return null to avoid exception.  caller can check for null this way...                 result = null;                 return true;             }              result = WrapResultObject(result);             return true;         }          public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)         {             if (indexes.Length == 1 && indexes[0] != null)             {                 if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))                 {                     // return null to avoid exception.  caller can check for null this way...                     result = null;                     return true;                 }                  result = WrapResultObject(result);                 return true;             }              return base.TryGetIndex(binder, indexes, out result);         }          private static object WrapResultObject(object result)         {             var dictionary = result as IDictionary<string, object>;             if (dictionary != null)                 return new DynamicJsonObject(dictionary);              var arrayList = result as ArrayList;             if (arrayList != null && arrayList.Count > 0)             {                 return arrayList[0] is IDictionary<string, object>                      ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))                      : new List<object>(arrayList.Cast<object>());             }              return result;         }     }      #endregion } 

You can use it like this:

string json = ...;  var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new DynamicJsonConverter() });  dynamic obj = serializer.Deserialize(json, typeof(object)); 

So, given a JSON string:

{   "Items":[     { "Name":"Apple", "Price":12.3 },     { "Name":"Grape", "Price":3.21 }   ],   "Date":"21/11/2010" } 

The following code will work at runtime:

dynamic data = serializer.Deserialize(json, typeof(object));  data.Date; // "21/11/2010" data.Items.Count; // 2 data.Items[0].Name; // "Apple" data.Items[0].Price; // 12.3 (as a decimal) data.Items[1].Name; // "Grape" data.Items[1].Price; // 3.21 (as a decimal) 
like image 111
Drew Noakes Avatar answered Sep 29 '22 07:09

Drew Noakes