Announcing the release of the Json pipelines for BizTalk Server, Rest (web-http) adapter was release in BT 2010 which opened up new playground for integration specialists, and we could boast of BizTalk server’s OOB support both Rest and Soap protocols, but the one thing that was still missing was Json support.
Here in the blog post I will discuss & demonstrate on how to add json support using custom pipeline components, the entire source code is available on GitHub including unit tests ,apart from BizTalk we need the ESB tool kit components installed (only the pipelines).
Scenario 1: We need to send out a Json Message to an external endpoint, one of the solution for this is to create a new PC and use the Newtonsoft Json libraries JsonConvert.SerializeObject method to convert the xml stream into an object and generate a json string, the following is the code and the pipeline implementation.
Xml to Json pipeline component (DotNetTypesToJsonConverter.cs) |
Json send pipeline. |
IBaseMessage IComponent.Execute(IPipelineContext pContext, IBaseMessage pInMsg) { Trace.WriteLine(“DotNetTypesToJsonConverter Pipeline – Entered Execute()”); Trace.WriteLine(“DotNetTypesToJsonConverter Pipeline – TypeName is set to: ” + TypeName); IBaseMessagePart bodyPart = pInMsg.BodyPart; if (bodyPart != null) { Stream originalStream = bodyPart.GetOriginalDataStream(); if (originalStream != null) { Type myClassType = Type.GetType(TypeName); object reqObj = PcHelper.FromXml(originalStream, myClassType); string jsonText = JsonConvert.SerializeObject(reqObj, myClassType, Formatting.None, new JsonSerializerSettings()); Trace.WriteLine(“DotNetTypesToJsonConverter output: ” + jsonText); byte[] outBytes = Encoding.ASCII.GetBytes(jsonText); var memStream = new MemoryStream(); memStream.Write(outBytes, 0, outBytes.Length); memStream.Position = 0; bodyPart.Data = memStream; pContext.ResourceTracker.AddResource(memStream); } } Trace.WriteLine(“DotNetTypesToJsonConverter Pipeline – Exited Execute()”); return pInMsg; } |
![]() |
Scenario 2: We need to receive a Json message from an external endpoint and convert it into Xml for BizTalk’s further processing, one of the solution for this is to create a new PC and use the Newtonsoft Json libraries , I used the idea from an existing blog post http://www.modhul.com/2013/04/30/restfully-getting-json-formatted-data-with-biztalk-2013/, to create an XML document with few minor enhancements, if a root node is specified, the new xml will be added as a child to it or else a new xml document will be created and the root node will be based on the json message, and as we know BizTalk needs a namespace so we use the ESB toolkit’s add namespace component to add new namespace to the Xml (more than one can be added) created in the previous stage and finally we use the XML disassembler component to inform BizTalk of the new xml document, the following is the code and the pipeline implementation.
Json to xml pipeline component |
Json receive pipeline. |
IBaseMessage IComponent.Execute(IPipelineContext pContext, IBaseMessage pInMsg) { string json; Trace.WriteLine(“JsonToXmlConverter Pipeline – Entered Execute()”); Trace.WriteLine(String.Format(“JsonToXmlConverter Pipeline – RootNode: {0}”, Rootnode)); var originalStream = pInMsg.BodyPart.GetOriginalDataStream(); using (TextReader reader = new StreamReader(originalStream)) { json = reader.ReadToEnd(); } Trace.WriteLine(String.Format(“JsonToXmlConverter Pipeline – Read JSON Data: {0}”, json)); Trace.WriteLine(String.Format(“JsonToXmlConverter Pipeline – Deserializing JSON to Xml…”)); try { // Append deserialized Xml data to master root node. XmlDocument xmlDoc =!string.IsNullOrWhiteSpace(Rootnode) ? JsonConvert.DeserializeXmlNode(json, Rootnode) : JsonConvert.DeserializeXmlNode(json); Trace.WriteLine(String.Format(“JsonToXmlConverter Pipeline – Xml: {0}”, xmlDoc.InnerXml)); var output = Encoding.ASCII.GetBytes(xmlDoc.InnerXml); var memoryStream = new MemoryStream(); memoryStream.Write(output, 0, output.Length); memoryStream.Position = 0; pInMsg.BodyPart.Data = memoryStream; } catch (Exception ex) { Trace.WriteLine(String.Format(“JsonToXmlConverter Pipeline – Exception: {0}”, ex.Message)); } pInMsg.BodyPart.Data.Position = 0; return pInMsg; } |
![]() |
The following video demo’s the end to end working solution:
Hi,
Good article. Thanks for sharing.
Question: I don’t see you use “XmlToJsonConverter” in the send pipeline, but you use “DotNetTypesToJsonConverter”. What is the reason behind this?
Regards,
Tuan
Good job Madhukar!
Hi I am getting the following error in the json to xml conversion pipeline component
There was a failure executing the receive pipeline: “Test.Json1.Pipeline.recJson, Test.Json1.Pipelines, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6c68eaf68da2c621
“Source: “JsonToXmlConverter” Receive Port: “testwq” URI: “D:\wqin\*.*” Reason: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))”
Any idea whats going wrong with the pipeline component. ?
hi , this is a weird error, can you narrow down the error to place of invocation ?? I mean writing few debug trace statements..
the actual error is due to array object in the json file . and the exxception statement is “XmlNodeConverter can only convert JSON that begins with an object”. This can be handled by specifying an array name while deserializing to xml node. For example : xmldoc = JsonConvert.DeserializeXmlNode(“{\”array\”:” + JsonText + “}”, “root”)
the typename property always returns value as null even if defined when using the component in BizTalk 2010.Any specific reason
Excellent solution