How to convert XML to JSON using C#/LINQ?
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)
);
}
}
}
How to convert JSON to XML or XML to JSON?
Yes. Using 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);
Documentation here: Converting between JSON and XML with Json.NET
Convert XML to JSON and then deserialize to object
The easiest way to deserialize your XML is to do so in one step using XmlSerializer
. You can do this by marking your List<T>
properties with [XmlElement]
to indicate they should be serialized as a collection of repeated elements without an outer container element:
public class ProductionOrderFile
{
public string ProductionOrderName { get; set; }
public string ProductCode { get; set; }
[System.Xml.Serialization.XmlElement]
public List<Batch> Batches { get; set; }
[System.Xml.Serialization.XmlElement]
public List<AggregationLevelConfiguration> Levels { get; set; }
[System.Xml.Serialization.XmlElement]
public List<VariableData> VariableData { get; set; }
}
And then do:
private ProductionOrderFile ParseProductionOrderFile(Stream inputStream)
{
var serializer = new XmlSerializer(typeof(ProductionOrderFile));
return (ProductionOrderFile)serializer.Deserialize(inputStream);
}
Sample fiddle #1.
That being said, if you insist on a two-step deserialization process using an intermediate XmlDocument
, you need to modify your code as follows:
Omit the root element by using
JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true)
when creating your intermediatejsonText
.This removes the root
"ProductionOrderFile": { ... }
property that does not appear inProductionOrderFile
and bubbles the nested properties up to the top level.Force the
<Batches>
,<Levels>
and<VariableData>
element(s) to be converted to JSON as arrays by following the instructions from Convert XML to JSON and force array.
Thus your code becomes:
private ProductionOrderFile ParseProductionOrderFile(Stream inputStream)
{
// var serializer = new JsonSerializer(); Not needed
XmlDocument doc = new XmlDocument();
doc.Load(inputStream);
foreach (var xPath in new [] { "//Batches", "//Levels", "//VariableData" })
{
foreach (var node in doc.SelectNodes(xPath).Cast<XmlElement>())
{
node.SetAttribute("xmlns:json", "http://james.newtonking.com/projects/json");
node.SetAttribute("Array", "http://james.newtonking.com/projects/json", XmlConvert.ToString(true));
}
}
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true);
return JsonConvert.DeserializeObject<ProductionOrderFile>(jsonText);
}
Sample fiddle #2.
XDocument or XmlDocument to JSON with C#
Use the method call
JsonConvert.SerializeXNode(x, Formatting.None, true);
this will omit the root node and should create what you expect.
NewtonSoft from XML to JSON
You will have to add an intermediate stage between the XML deserialization and the Json Serialization. When you deserialize the XML to the class, create some new classes that will output to the JSON format you like, then implement some logic to create the JSON classes from the XML classes.
Converting XML to JSON with complex XML data
Using Linq to XML
XDocument xml = //...
var result = xml.Elements("job")
.Select(job => job
.Elements("properties")
.ToDictionary(p => p.Element("name").Value, p => p.Element("value").Value)
);
result
will contain a collection of dictionaries, that when serialized,
string json = JsonConvert.SerializeObject(result);
using something like Json.Net, will produce the desired result.
The above example does not include any validation checks, but that can be easily added. The example was just to show how the data can be transformed into the desired model.
Convert XML to Json Array when only one object
Read this documentation about Serialize Xml Node
You can force JSON Array this way
var xml = @"<Items xmlns:json='http://james.newtonking.com/projects/json' >
<Item json:Array='true'>
<Name>name</Name>
<Detail>detail</Detail>
</Item>
</Items>";
DEMO
Convert from HUGE Xml to Json
Try the recommended Microsoft technique:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/how-to-perform-streaming-transform-of-large-xml-documents
So, for example, you have the following part of code:
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NodeType == XmlNodeType.Element
&& reader.Name == "Item")
{
item = XElement.ReadFrom(reader) as XElement;
if (item != null)
{
//here you can get data from your array object
//and put it to your JSON stream
}
}
}
If you want to define the type of element you can check if it has children:
How to check if XElement has any child nodes?
It should work good in pair with streaming of JSON. For more info about JSON steaming look into: Writing JSON to a stream without buffering the string in memory
Related Topics
Mono on Debian: Could Not Find File "/Srv/Www/Proj/Bin\Roslyn\Csc.Exe"
Converting a Byte to a Binary String in C#
Shell Script File(.Sh) Does Not Run from C# Core on Linux
.Net Class to Execute Remotely on Linux Over Ssh
Linux to Windows Bad Encoding Response
Asp.Net Vnext Kestrel + Windows Authentication
Mono: Is Remote Debugging Possible with Monodevelop
Which Linux Distribution Is Best for Developing a Mono Application in a Virtual Machine
C# Task.Waitall() in .Net and Mono
Soap Authentication Fails When Running a C# App on a Linux Box
HTMLagilitypack HTMLweb.Load Returning Empty Document
Reading/Writing from Named Pipes Under Mono/Linux
Execute SQL Script on SQL Server Using C#
C#: Referencing or Using .So Files in .Net Core on Linux
Open Source HTML to PDF Renderer with Full CSS Support