Dynamic JSON Converter and CRM 2011

The Dynamics CRM 2011 REST API is a powerful integration option for XRM developers.  In a past post I attempted to demonstrate a simplified example of a console app grabbing some SQL data from a non-CRM source and posting that data to CRM using the REST API.  Retrieving data back from CRM is just as straightforward but since it returns as JSON you need a strategy to handle that. I wanted to find a way I could deserialize JSON on the fly dynamically, below are my results.  I have greatly parsed down the example, hopefully making it easier for readers to comprehend my approach but at the end of this post I will include the full DynamicJsonConverter class for your use.

The JavaScriptSerializer class is used internally by the Dynamics CRM 2011 asynchronous communication layer to serialize and deserialize the data that is passed between the browser and the Web server. You cannot access that instance of the serializer. However, this class exposes a public API. Therefore, you can use the class when you want to work with JavaScript Object Notation (JSON) in managed code.

To serialize and deserialize types that are not natively supported by JavaScriptSerializer, implement custom converters by using the JavaScriptConverter class. Then register the converters by using the RegisterConverters method which is where our DynamicJsonConverter class comes in.

Step 1) First we get some data from a XRM proxy service based on the concepts found here Dynamics CRM 2011 REST API

publicdynamic GetListofEntities(string entityName, string entityField)

        {

         

   XRMServiceClient xrm = newXRMServiceClient();

          string json = xrm.GetAllEntititiesSpecifyFields(entityName, entityField);

 

 

 

Step 2)

We declare a JavaScriptSerializer dynamic object and register our custom converter.

          var serializer = newJavaScriptSerializer();

          serializer.RegisterConverters(new[]{newJsonExtension.DynamicJsonConverter()});

 

          dynamic data = serializer.Deserialize(json, typeof(object));

 

          return data.Items;

         }

 

 

 

The sample code above would then be implemented by code similar to below.  In this example (Step 3 below) we are just passing in a email address of a contact and getting back the corresponding contact entity record from CRM.  Next we can store our contact in local variables or as a class which I also show below.

Notice here that using these methods we are able to use dot notation to access entity attributes (entityRecord.telephone1).  That’s pretty cool considering our GetListofEntities method above has no concept of a contact or any of the specific attributes, it only knows how to fetch JSON based data and convert it. Even the keyword Items is dynamic and resolved only at runtime.

Step 3)

foreach (var entityRecord in GetListofEntities(“contact”, “emailaddress1”))

{

first = newContact() { FirstName = entityRecord.firstname };

last = newContact() { LastName = entityRecord.lastname };

phone = newContact() { Phone = entityRecord.telephone1 };

 

}

 

publicclassContact : IEntity

  {

publicstring FirstName { get; set; }

publicstring LastName { get; set; }

publicstring Phone { get; set; }

  }

 

 

Here’s the JSONConverter class in sound working order.  However the example code above is not necessarily Intended for direct use.

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.Helpers;

using System.Web.Script.Serialization;

namespace JSONConverter

{

    publicclassJsonExtension

    {

        publicclassDynamicJsonConverter : JavaScriptConverter

        {

            publicoverrideobject Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)

            {

                if (dictionary == null)

                    thrownewArgumentNullException(“dictionary”);

 

                return type == typeof(object) ? newDynamicJsonObject(dictionary) : null;

            }

 

            publicoverrideIDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)

            {

                thrownewNotImplementedException();

            }

 

            publicoverrideIEnumerable<Type> SupportedTypes

            {

                get { returnnewReadOnlyCollection<Type>(newList<Type>(new[] { typeof(object) })); }

            }

 

            privatesealedclassDynamicJsonObject : DynamicObject

            {

                privatereadonlyIDictionary<string, object> _dictionary;

 

                public DynamicJsonObject(IDictionary<string, object> dictionary)

                {

                    if (dictionary == null)

                        thrownewArgumentNullException(“dictionary”);

                    _dictionary = dictionary;

                }

 

                publicoverridestring ToString()

                {

                    var sb = newStringBuilder(“{“);

                    ToString(sb);

                    return sb.ToString();

                }

 

                privatevoid 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 isstring)

                        {

                            sb.AppendFormat(“{0}:\”{1}\””, name, value);

                        }

                        elseif (value isIDictionary<string, object>)

                        {

                            newDynamicJsonObject((IDictionary<string, object>)value).ToString(sb);

                        }

                        elseif (value isArrayList)

                        {

                            sb.Append(name + “:[“);

                            var firstInArray = true;

                            foreach (var arrayValue in (ArrayList)value)

                            {

                                if (!firstInArray)

                                    sb.Append(“,”);

                                firstInArray = false;

                                if (arrayValue isIDictionary<string, object>)

                                    newDynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);

                                elseif (arrayValue isstring)

                                    sb.AppendFormat(“\”{0}\””, arrayValue);

                                else

                                    sb.AppendFormat(“{0}”, arrayValue);

                            }

                            sb.Append(“]”);

                        }

                        else

                        {

                            sb.AppendFormat(“{0}:{1}”, name, value);

                        }

                    }

                    sb.Append(“}”);

                }

 

                publicoverridebool TryGetMember(GetMemberBinder binder, outobject result)

                {

                    if (!_dictionary.TryGetValue(binder.Name, out result))

                    {

                        // return null to avoid exception.  caller can check for null this way…

                        result = null;

                        returntrue;

                    }

 

                    var dictionary = result asIDictionary<string, object>;

                    if (dictionary != null)

                    {

                        result = newDynamicJsonObject(dictionary);

                        returntrue;

                    }

 

                    var arrayList = result asArrayList;

                    if (arrayList != null && arrayList.Count > 0)

                    {

                        if (arrayList[0] isIDictionary<string, object>)

                            result = newList<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => newDynamicJsonObject(x)));

                        else

                            result = newList<object>(arrayList.Cast<object>());

                    }

 

                    returntrue;

                }

            }

        }

    }

}