2

i have kind of wired requirement for converting JSON to xml. we have an API that returns the JSON response as below.

{
   "status":"Error",
   "errorMessages":{
      "1001":"Schema validation Error"
   }
}

We want to convert this JSON to XML as below using c#

<root>
  <status>ERROR</status>
  <errorMessages>
    <ErrorCode>1001</ErrorCode>
    <ErrorDescription>Schema validation Error</ErrorDescription>    
  </errorMessages>
</root>

The API team is very resistant to change the way there are generating the JSON. So i have to find a way to convert this json to XML.

I am getting the below error when i try to convert

XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

"JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path errorMessages

thanks for the help in advance. :)

abhi pm
  • 41
  • 1
  • 7
  • when i try to run the deserializeXmlNode method i am getting the below error `XmlDocument doc = JsonConvert.DeserializeXmlNode(json); ` ` i am getting the below error when i try to convert "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'errorMessages ` – abhi pm Mar 21 '18 at 12:44
  • You need to write a custom transformer for this JSON because 1) it has no root node (as the error says) and 2) it has properties that begin with a number (which would be invalid XML element names). There is no direct conversion path. – Dan Wilson Mar 21 '18 at 13:19

4 Answers4

2

At first, I would hardly recommend that your API team provides a valid JSON object. Otherwise you will have to write a converter that does the job. The converter could look like this:

using System.Collections.Generic;

namespace Json
{
    using System.IO;
    using System.Xml.Serialization;

    using Newtonsoft.Json.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            var converter = new Converter();
            converter.Convert();
        }
    }

    class Converter
    {
        public void Convert()
        {
            //  your JSON string goes here
            var jsonString = @"{""status"":""Error"",""errorMessages"":{ ""1001"":""Schema validation Error"", ""1953"":""Another error""}}";

            // deconstruct the JSON
            var jObject = JObject.Parse(jsonString);
            var root = new Root { Status = jObject["status"].ToString(), ErrorMessages = new List<ErrorMessage>() };
            foreach (var errorMessageJsonObject in jObject["errorMessages"])
            {
                var jProperty = (JProperty)errorMessageJsonObject;
                var errorCode = System.Convert.ToInt16(jProperty.Name);
                var errorDescription = jProperty.Value.ToString();
                var errorMessage = new ErrorMessage() { ErrorCode = errorCode, ErrorDescription = errorDescription};

                root.ErrorMessages.Add(errorMessage);
            }

            // serialize as XML
            var xmlSerializer = new XmlSerializer(typeof(Root));
            string xml;
            using (StringWriter textWriter = new StringWriter())
            {
                xmlSerializer.Serialize(textWriter, root);
                xml = textWriter.ToString();
            }
        }
    }

    public class Root
    {
        public string Status;

        public List<ErrorMessage> ErrorMessages;
    }

    public class ErrorMessage
    {
        public int ErrorCode;

        public string ErrorDescription;
    }
}

With this, you will read the JSON, deconstruct it into a proper object and serialize it as XML.

mu88
  • 4,156
  • 1
  • 23
  • 47
  • Thanks a lot @mu88 this worked. :) we have asked out API team to change it but we are not sure if that will be doing it .. – abhi pm Mar 21 '18 at 15:21
  • Great! If you like this post, please give it your vote and/or mark it as an answer. – mu88 Mar 21 '18 at 15:25
1

if you are using asp.net web api. Its already can return xml response just add an accept header like

Accept: application/xml

arslanaybars
  • 1,813
  • 2
  • 24
  • 29
  • when i add the above header its will fail as the xml element cannot start with an integer. ` ERROR <1274>Schema validation Error1274> ` – abhi pm Mar 21 '18 at 12:50
  • i am consuming this service in biztalk server. So i need to write a custom c# component that does this conversion. – abhi pm Mar 21 '18 at 12:56
  • check it : https://stackoverflow.com/questions/814001/how-to-convert-json-to-xml-or-xml-to-json – arslanaybars Mar 21 '18 at 12:59
1

From the documentation at https://www.newtonsoft.com/json/help/html/ConvertingJSONandXML.htm

string json = @"{
  '?xml': {
    '@version': '1.0',
    '@standalone': 'no'
  },
  'root': {
    'person': [
      {
        '@id': '1',
        'name': 'Alan',
        'url': 'http://www.google.com'
      },
      {
        '@id': '2',
        'name': 'Louis',
        'url': 'http://www.yahoo.com'
      }
    ]
  }
}";

XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
Matthias Grün
  • 1,466
  • 1
  • 7
  • 12
0

Use the JsonConvert class which contains helper methods for this precise purpose:

// To convert an XML node contained in string xml into a JSON string   
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);

// To convert JSON text contained in string json into an XML node
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

The Completed Documentation : Here

Carlos Henrique
  • 353
  • 4
  • 19
  • hi carlos thanks for the response. i am getting the below error when i try to convert "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'errorMessages'" – abhi pm Mar 21 '18 at 12:40
  • Hi Abhi pm, try it if possible for you. [link](https://stackoverflow.com/questions/16562101/converting-json-to-xml) – Carlos Henrique Mar 21 '18 at 13:24