I have the following XML file that I need to convert to JSON in the server. Initially I thought I would convert it to a Dictionary and then use the JavaScriptSerializer to turn it into JSON but since each column could have a different value type, I don't think it would work. Has anyone done something similar before in C#/LINQ?
I need to preserve the Value Types(Boolean, String, Integer) of each column.
I would appreciate any advice on this as Im just starting to work with XML. Thanks.
<Columns>
<Column Name="key1" DataType="Boolean">True</Column>
<Column Name="key2" DataType="String">Hello World</Column>
<Column Name="key3" DataType="Integer">999</Column>
</Columns>
To convert an XML document to JSON, follow these steps: Select the XML to JSON action from the Tools > JSON Tools menu. Choose or enter the Input URL of the XML document. Choose the path of the Output file that will contain the resulting JSON document.
Once you have an XmlDocument object, you can use Json.NET to convert that object into a Json representation. var json = JsonConvert. SerializeXmlNode(doc, Formatting.
A JSON is a lightweight data-interchange format and the format of JSON is like a key-value pair. We can convert a JSONObject into an XML format using org. json. XML class, this provides static methods to convert an XML text into a JSONObject and to convert a JSONObject into an XML text.
JSON is Unlike XML Because The biggest difference is: XML has to be parsed with an XML parser. JSON can be parsed by a standard JavaScript function.
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Xml.Linq;
class Program
{
static void Main()
{
var xml =
@"<Columns>
<Column Name=""key1"" DataType=""Boolean"">True</Column>
<Column Name=""key2"" DataType=""String"">Hello World</Column>
<Column Name=""key3"" DataType=""Integer"">999</Column>
</Columns>";
var dic = XDocument
.Parse(xml)
.Descendants("Column")
.ToDictionary(
c => c.Attribute("Name").Value,
c => c.Value
);
var json = new JavaScriptSerializer().Serialize(dic);
Console.WriteLine(json);
}
}
produces:
{"key1":"True","key2":"Hello World","key3":"999"}
Obviously this treats all the values as strings. If you want to keep the underlying type semantics you could do the following:
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Xml.Linq;
class Program
{
static void Main()
{
var xml =
@"<Columns>
<Column Name=""key1"" DataType=""System.Boolean"">True</Column>
<Column Name=""key2"" DataType=""System.String"">Hello World</Column>
<Column Name=""key3"" DataType=""System.Int32"">999</Column>
</Columns>";
var dic = XDocument
.Parse(xml)
.Descendants("Column")
.ToDictionary(
c => c.Attribute("Name").Value,
c => Convert.ChangeType(
c.Value,
typeof(string).Assembly.GetType(c.Attribute("DataType").Value, true)
)
);
var json = new JavaScriptSerializer().Serialize(dic);
Console.WriteLine(json);
}
}
produces:
{"key1":true,"key2":"Hello World","key3":999}
And if you cannot modify the underlying XML structure you will need a custom function that will convert between your custom types and the underlying .NET type:
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Xml.Linq;
class Program
{
static void Main()
{
var xml =
@"<Columns>
<Column Name=""key1"" DataType=""Boolean"">True</Column>
<Column Name=""key2"" DataType=""String"">Hello World</Column>
<Column Name=""key3"" DataType=""Integer"">999</Column>
</Columns>";
var dic = XDocument
.Parse(xml)
.Descendants("Column")
.ToDictionary(
c => c.Attribute("Name").Value,
c => Convert.ChangeType(
c.Value,
GetType(c.Attribute("DataType").Value)
)
);
var json = new JavaScriptSerializer().Serialize(dic);
Console.WriteLine(json);
}
private static Type GetType(string type)
{
switch (type)
{
case "Integer":
return typeof(int);
case "String":
return typeof(string);
case "Boolean":
return typeof(bool);
// TODO: add any other types that you want to support
default:
throw new NotSupportedException(
string.Format("The type {0} is not supported", type)
);
}
}
}
Is it necessary to use LINQ? Otherwise you can try this:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
Taken from this post.
For deep nesting of XML elements with more and unknown attributes you can use this recursion:
private static string XmlToJson(string xmlString)
{
return new JavaScriptSerializer().Serialize(GetXmlValues(XElement.Parse(xmlString)));
}
private static Dictionary<string, object> GetXmlValues(XElement xml)
{
var attr = xml.Attributes().ToDictionary(d => d.Name.LocalName, d => (object)d.Value);
if (xml.HasElements) attr.Add("_value", xml.Elements().Select(e => GetXmlValues(e)));
else if (!xml.IsEmpty) attr.Add("_value", xml.Value);
return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
}
For your example the result will be:
{
"Columns":{
"_value":[
{
"Column":{
"Name":"key1",
"DataType":"Boolean",
"_value":"True"
}
},
{
"Column":{
"Name":"key2",
"DataType":"String",
"_value":"Hello World"
}
},
{
"Column":{
"Name":"key3",
"DataType":"Integer",
"_value":"999"
}
}
]
}
}
And for more complex XML case like this, you can check the JSON analogue here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With