Jak przekonwertować XML na JSON za pomocą C# / LINQ?
Mam następujący plik XML, który muszę przekonwertować na JSON na serwerze. Początkowo myślałem, że będę przekonwertować go do słownika, a następnie użyć JavaScriptSerializer, aby przekształcić go w JSON, ale ponieważ każda kolumna może mieć inny typ wartości, myślę, że nie będzie działać. Czy ktoś już zrobił coś podobnego w C# / LINQ?
Muszę zachować typy wartości (Boolean, String, Integer) każdej kolumny.
Byłbym wdzięczny za każdą radę w tej sprawie, ponieważ dopiero zaczynam praca z XML. Dzięki.
<Columns>
<Column Name="key1" DataType="Boolean">True</Column>
<Column Name="key2" DataType="String">Hello World</Column>
<Column Name="key3" DataType="Integer">999</Column>
</Columns>
3 answers
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);
}
}
Produkuje:
{"key1":"True","key2":"Hello World","key3":"999"}
Oczywiście traktuje to wszystkie wartości jako ciągi znaków. Jeśli chcesz zachować podstawową semantykę typu, możesz wykonać następujące czynności:
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);
}
}
Produkuje:
{"key1":true,"key2":"Hello World","key3":999}
A jeśli nie możesz zmodyfikować podstawowej struktury XML, będziesz potrzebował niestandardowej funkcji, która będzie konwertować między twoimi typami niestandardowymi a bazowym typem. Net:
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)
);
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-20 12:02:00
Czy konieczne jest używanie LINQ? W przeciwnym razie możesz spróbować tego:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
Zaczerpnięte z tego postu .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:30
Do głębokiego zagnieżdżania elementów XML z większą liczbą nieznanych atrybutów można użyć tej rekurencji:
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 } };
}
Dla Twojego przykładu wynik będzie następujący:
{
"Columns":{
"_value":[
{
"Column":{
"Name":"key1",
"DataType":"Boolean",
"_value":"True"
}
},
{
"Column":{
"Name":"key2",
"DataType":"String",
"_value":"Hello World"
}
},
{
"Column":{
"Name":"key3",
"DataType":"Integer",
"_value":"999"
}
}
]
}
}
I dla bardziej złożonych przypadków XML, takich jak to , możesz sprawdzić Analog JSON tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-04 11:35:35