DEV Community

Cover image for Transforming data from JSON to XML and XML to JSON with C#
Markus Meyer
Markus Meyer

Posted on • Originally published at markusmeyer.hashnode.dev

Transforming data from JSON to XML and XML to JSON with C#

Table of Contents

1 Objective

2 Data Transfer Object (DTO) and data samples

3 Root node / root property

3.1 Add root property to JSON

3.2 Remove root property from JSON

4 Transformation

4.1 Transform JSON into XML

4.2 Transform XML into JSON

5 Azure Function

6 Alternative - Newtonsoft

7 Complete solution

1 Objective

A JSON document has to be transformed into XML. If the XML is transformed back into JSON, the initial JSON has to equal the transformed back JSON.
The solution will be provided as an Azure Function.

Sequence Diagram

Additional requirements which have to be met:

  • JSON-Document has to contain a root property
  • Data types have to be specified (string, int, boolean,...)
  • XML Attributes has to be supported

2 Data Transfer Object (DTO) and data samples

To ensure that XML-attributes and data types can be used, a C# DTO is required.
Like the required XML root node, the JSON document shall also have a root property.

Person class:

[XmlRoot("person")]
[JsonObject(Title = "Person")]
public class Person
{
    [XmlElement("firstname")]
    public string FirstName { get; set; }

    [XmlElement("lastname")]
    public string LastName { get; set; }

    [XmlAttribute("gender")]
    public string Gender { get; set; }

    [XmlElement("age")]
    public int Age { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

XML for Person class:

<?xml version="1.0" encoding="utf-8" ?>
<person gender="female">
  <firstname>Anna</firstname>
  <lastname>Smith</lastname>
  <age>42</age>
</person>
Enter fullscreen mode Exit fullscreen mode

JSON for Person class:

{
  "Person": {
    "FirstName": "Anna",
    "LastName": "Smith",
    "Gender": "female",
    "Age": 42
  }
}
Enter fullscreen mode Exit fullscreen mode

3 Root node / root property

Unfortunately, it's not straight forward to have a root property in JSON.
Usually, I do not have to care about, because I'm only using JSON documents.
Then I use a wrapper class:

public class PersonRoot
{
    public Person Person { get; set; }
}

public class Person
{
    public string FirstName { get; set; }

    // ...
}

Enter fullscreen mode Exit fullscreen mode

In my current case, I do not like this way:

The class PersonRoot will only be used for the JSON data.
For the XML data, it's useless.

A solution to solve this problem is using class attribute [JsonObject(Title = "Person")] and add some code.

3.1 Add root property to JSON

The code below creates a new JObject based on the JsonObject attribute and adds the initial JObject as a child by transforming XML into JSON:

Add root property:


[JsonObject(Title = "Person")]
public class Person
{
    // ... 
}



Person obj = new Person();
var jsonObjectAttribute = typeof(T).GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
var jsonValue = JValue.FromObject(obj);
var jsonObject =  new JObject(new JProperty(jsonObjectAttribute.Title, jsonValue));
Enter fullscreen mode Exit fullscreen mode

3.2 Remove root property from JSON

The code below creates a new JObject based on the JSON document.
For transforming JSON into XML, the root JSON property has to be removed.
JsonObject attribute is used to get the JSON root property.

Remove root property:

[JsonObject(Title = "Person")]
public class Person
{
    // ... 
}

var jsonObjectAttribute = typeof(T).GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
JObject root = JObject.Parse(json);
var data = root[jsonObjectAttribute.Title];

Enter fullscreen mode Exit fullscreen mode

4 Transformation

It's time to put all the things together.

4.1 Transform JSON into XML

The code removes the root property, deserializes the JSON document to the object and the XmlSerializer is used to create an XML string.

Transform JSON into XML:

var result = Transformer.TransformJsonToXml<Person>(json);
Enter fullscreen mode Exit fullscreen mode
public static string TransformJsonToXml<T>(string json)
{
    // Remove root property
    var jsonObjectAttribute = typeof(T).GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
    JObject root = JObject.Parse(json);
    var data = root[jsonObjectAttribute.Title];

    var obj = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(data));

    var serializer = new XmlSerializer(typeof(T));
    var stringWriter = new StringWriter();
    using var xmlWriter = XmlWriter.Create(stringWriter);
    var xmlSerializerNamespaces = new XmlSerializerNamespaces();
    xmlSerializerNamespaces.Add("","");
    serializer.Serialize(xmlWriter, obj, xmlSerializerNamespaces);
    return stringWriter.ToString();
}


Enter fullscreen mode Exit fullscreen mode

4.2 Transform XML into JSON

The code deserializes the XML document by using the XmlSerializer to the object, adds the root property and the serialized object will be returned.

Transform XML into JSON:

var result = Transformer.TransformXmlToJson<Person>(xml);
Enter fullscreen mode Exit fullscreen mode
public static string TransformXmlToJson<T>(string xml)
{
    var serializer = new XmlSerializer(typeof(T));
    using var stringReader = new System.IO.StringReader(xml);
    using var xmlReader = XmlReader.Create(stringReader);
    var obj = (T)serializer.Deserialize(xmlReader);

    // Add root property
    var jsonObjectAttribute = typeof(T).GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
    var jsonValue = JValue.FromObject(obj);
    var jsonObject =  new JObject(new JProperty(jsonObjectAttribute.Title, jsonValue));

    var settings = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented };
    return JsonConvert.SerializeObject(jsonObject, settings);
}
Enter fullscreen mode Exit fullscreen mode

5. Azure Function

This is straight forward for returning the JSON document:

 return new OkObjectResult(JObject.Parse(result));
Enter fullscreen mode Exit fullscreen mode

image
For returning the XML document OkObjectResult cannot be used:

 return new ContentResult() { Content = result, ContentType = "application/xml", StatusCode = 200 };
Enter fullscreen mode Exit fullscreen mode

image

6. Alternative - Newtonsoft

The Newtonsoft JSON library also supports transforming data into JSON or XML:
Newtonsoft: Converting between JSON and XML

But there are a few things which do not match my requirements:

  • prefixed attributes
    • so I have to include additional code to get rid of this
  • no data types
    • all data types are strings

7. Complete solution

The complete solution can be found in my GitHub repository.

Top comments (1)

Collapse
 
lantis_5fc22a3d98c profile image
Lantis Pillay

Great Article Markus,
the XML - Json function works well on the basic XML file (fig. 1 above), but I ran into problems when used with an XML file with namespaces and complex levels. you have any advice on how to handle this sort of file. TX