From JSON to CRM WebApi object using acmemapper

Hello everyone,

In some scenarios, we have to get JSON as input data and then use it in order to perform an action within another system.
I'll introduce the usage of an easy and fast mapping system.

Table of content :

  1. What is acmeapper ?
  2. JSON data to CRM Rest entity (json object)
  3. Perform the transformation of the json.
  4. What to do with that ?

1. What is acmemapper ?

A former colleague developped a mapping system called acmemapper supporting various mapping scenarios with lisibility & maintenance as main drivers.

A dotnet core version is available on github and as a nuget package. A 5 minutes long how-to is available here.

acmemapper is supporting nested properties and also reworking of value outputs which is useful in Dynamics CRM context.

2. JSON data to CRM Rest entity (json object)

Let's see how you should perform the conversion from :

{
  "revenue" : 3873600,
  "name": "3D Printer Purchase - Modified",
  "closedDate": "2016-05-08",
  "purchase": 3,
  "reference": "6634f32e-4be5-e511-80fe-00155d09ab01",
  "client" : "475b158c-541c-e511-80d3-3863bb347ba8"
}

to json ready for the Dynamics 365 WebApi :

{
  "actualvalue" : 3873600,
  "name": "3D Printer Purchase - Modified",
  "estimatedclosedate": "2016-05-08",
  "purchasetimeframe": 3,
  "opportunityid": "6634f32e-4be5-e511-80fe-00155d09ab01",
  "parentaccount@databind" : "/accounts(475b158c-541c-e511-80d3-3863bb347ba8)"
}

The good point with the WebApi is that it "only" needs flat values.

As example, the field parentaccount@databind is a lookup to contact entity from the opportunity. While using the SDK you would have var lookupField = new EntityReference("account", guid); with WebApi, you just need the Guid and the entity name related.

To achieve this rework of JSON, we will now focus on the mapping itself.

{
  "$version": "1.0",
  "opportunity": [
    {
      "systemA": {
        "property": "revenue"
      },
      "crm": {
        "property": "actualvalue"
      }
    },
    {
      "systemA": {
        "property": "parentaccount"
      },
      "crm": {
        "property": "parentaccount@databind",
        "patternValue": "/contacts({value})"
      }
    }
  ]
}

In that example, we can see how we simply map 2 fields in order to rename the property name, from "revenue" to "actualrevenue" in this case. This will be the same idea for the others fields except the parentaccount field.

For the parentaccount field, we have an extra property patternValue which will allow you to rework (not the property naming) the value ouput.
All you have to do is defining pattern/string in which the original value will be put in with the {value} variable.

So the value will be transformed from 475b158c-541c-e511-80d3-3863bb347ba8 to /accounts(475b158c-541c-e511-80d3-3863bb347ba8) in our sample.

3. Perform the transformation

Now that the mapping is done, we can now perform the action we are looking for since the beginning, the actual transformation of the input JSON into the transformed JSON :

// We instanciate the mapper object
var mapper = new acmemapper.Mapper("systemA", "crm");  
// We convert the json from the input into our "crm" like object in json
var transformedData = mapper.Map<JObject, JObject>("opportunity", myJsonEntry);  

We need to take care of two things here :

  • The creation of mapper object needs to embedded the name you put in the mapping field. Here "systemA" is the from system and "CRM" is the destination system.
  • the object type you want to convert opportunity in my case.

This allow you to have one mapping json file which can convert various object types with various systems.

What to do with that ?

After the acmemapper effect, you have data in JSON format ready to be pushed to your CRM instance using the WebApi.

A simple Patch request with the result of acmemapper in the body of the request will perform the update of your record in the CRM.

Something similar to : (replace the webapi version and opportunity guid)

PATCH [Organization URI]/api/data/v9.0/opportunity(00000000-0000-0000-0000-000000000001) HTTP/1.1  
Content-Type: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0

{
  "actualvalue" : 3873600,
  "name": "3D Printer Purchase - Modified",
  "estimatedclosedate": "2016-05-08",
  "purchasetimeframe": 3,
  "opportunityid": "6634f32e-4be5-e511-80fe-00155d09ab01",
  "parentaccount@databind" : "/accounts(475b158c-541c-e511-80d3-3863bb347ba8)"
}

Will give you a response of :

HTTP/1.1 204 No Content  
OData-Version: 4.0  

Conclusion

This is a quick explanation to show you how to use acmemapper in the "CRM" context.
In few minutes you can connect two systems which are managing the data totally a different ways and being able to reuse from one system to another the same data.

Hope this can help,
Happy CRM'in and Mapp'in !

Clément

Clement

Dynamics 365 CRM & Power Platform addict.