将 xml 字符串序列化为对象并序列化为 json
Serialize xml string to object and to json
我有以下 xml 字符串格式,其中 属性 密钥是随机的且未知但始终以字母数字字符开头
<properties>
<property key="EventId">3300</property>
<property key="source">car</property>
<property key="type">omega</property>
<property key="a341414">any value</property>
<property key="arandomstring_each_time_different">any value</property>
....
</properties>
如何实现如下格式
{
"properties":
{
"EventId": "3300",
"source": "car",
...
}
}
我尝试了以下代码的一些变体,但没有成功
XDocument doc = XDocument.Parse(string);
string jsonText = JsonConvert.SerializeXNode(doc);
var dynamic = JsonConvert.DeserializeObject<ExpandoObject>(jsonText);
产出
{
"properties":{
"property":[
{
"@key":"EventId",
"#text":"3300"
},
{
"@key":"source",
"#text":"car"
},
...
]
}
}
如果你想完全依赖 Json.Net 那么你也可以这样做:
var docInXml = XDocument.Parse("...");
var docInJson = JsonConvert.SerializeXNode(docInXml);
var semiParsedJson = JObject.Parse(docInJson);
var propertyCollection = semiParsedJson["properties"]["property"] as JArray;
var keyValueMapping = new Dictionary<string, string>();
foreach(var item in propertyCollection.Children())
{
keyValueMapping.Add((string)item["@key"], (string)item["#text"]);
}
var result = new JObject(new JProperty("properties", JObject.FromObject(keyValueMapping)));
让我们逐行查看代码:
var docInXml = XDocument.Parse("...");
- 它将 xml 字符串解析为
XDocument
var docInJson = JsonConvert.SerializeXNode(docInXml);
- 它将
XDocument
序列化为 json
{
"properties":{
"property":[
{
"@key":"EventId",
"#text":"3300"
},
{
"@key":"source",
"#text":"car"
},
{
"@key":"type",
"#text":"omega"
},
{
"@key":"a341414",
"#text":"any value"
},
{
"@key":"arandomstring_each_time_different",
"#text":"any value"
}
]
}
}
var semiParsedJson = JObject.Parse(docInJson);
- 半解析json能够进行节点遍历
var propertyCollection = semiParsedJson["properties"]["property"] as JArray;
- 它将
property
集合检索为数组
var keyValueMapping = new Dictionary<string, string>();
- 它为关键属性和文本值定义了一个临时存储空间
foreach(var item in propertyCollection.Children())
- 它遍历数组的项目
keyValueMapping.Add((string)item["@key"], (string)item["#text"]);
- 它检索所需的字段并将它们从
JObject
转换为 string
- 它将它们存储在中间存储器中
JObject.FromObject(keyValueMapping)))
- 它将
Dictionary
转换为 JObject
{
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
var result = new JObject(new JProperty("properties", ...));
- 最后,它围绕上面创建的
JObject
创建了一个包装器
{
"properties": {
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
}
Json.NET 的行为如 Converting between JSON and XML:
中所述
Single child text nodes are a value directly against an element, otherwise they are accessed via #text.
因为你的 <property>
节点有一个属性,值被放在 #text
属性.
但是为什么要用Json.NET把XElement
转换成ExpandoObject
呢?直接使用 LINQ 进行转换很简单 XML:
var doc = XDocument.Parse(xml);
IDictionary<string, object> properties = new ExpandoObject();
foreach (var property in doc.Root.Elements("property"))
properties.Add(property.Attribute("key").Value, property.Value);
dynamic d = new ExpandoObject();
d.properties = properties;
根据需要,结果为:
{
"properties": {
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
}
演示 fiddle here.
我有以下 xml 字符串格式,其中 属性 密钥是随机的且未知但始终以字母数字字符开头
<properties>
<property key="EventId">3300</property>
<property key="source">car</property>
<property key="type">omega</property>
<property key="a341414">any value</property>
<property key="arandomstring_each_time_different">any value</property>
....
</properties>
如何实现如下格式
{
"properties":
{
"EventId": "3300",
"source": "car",
...
}
}
我尝试了以下代码的一些变体,但没有成功
XDocument doc = XDocument.Parse(string);
string jsonText = JsonConvert.SerializeXNode(doc);
var dynamic = JsonConvert.DeserializeObject<ExpandoObject>(jsonText);
产出
{
"properties":{
"property":[
{
"@key":"EventId",
"#text":"3300"
},
{
"@key":"source",
"#text":"car"
},
...
]
}
}
如果你想完全依赖 Json.Net 那么你也可以这样做:
var docInXml = XDocument.Parse("...");
var docInJson = JsonConvert.SerializeXNode(docInXml);
var semiParsedJson = JObject.Parse(docInJson);
var propertyCollection = semiParsedJson["properties"]["property"] as JArray;
var keyValueMapping = new Dictionary<string, string>();
foreach(var item in propertyCollection.Children())
{
keyValueMapping.Add((string)item["@key"], (string)item["#text"]);
}
var result = new JObject(new JProperty("properties", JObject.FromObject(keyValueMapping)));
让我们逐行查看代码:
var docInXml = XDocument.Parse("...");
- 它将 xml 字符串解析为
XDocument
var docInJson = JsonConvert.SerializeXNode(docInXml);
- 它将
XDocument
序列化为 json
{
"properties":{
"property":[
{
"@key":"EventId",
"#text":"3300"
},
{
"@key":"source",
"#text":"car"
},
{
"@key":"type",
"#text":"omega"
},
{
"@key":"a341414",
"#text":"any value"
},
{
"@key":"arandomstring_each_time_different",
"#text":"any value"
}
]
}
}
var semiParsedJson = JObject.Parse(docInJson);
- 半解析json能够进行节点遍历
var propertyCollection = semiParsedJson["properties"]["property"] as JArray;
- 它将
property
集合检索为数组
var keyValueMapping = new Dictionary<string, string>();
- 它为关键属性和文本值定义了一个临时存储空间
foreach(var item in propertyCollection.Children())
- 它遍历数组的项目
keyValueMapping.Add((string)item["@key"], (string)item["#text"]);
- 它检索所需的字段并将它们从
JObject
转换为string
- 它将它们存储在中间存储器中
JObject.FromObject(keyValueMapping)))
- 它将
Dictionary
转换为JObject
{
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
var result = new JObject(new JProperty("properties", ...));
- 最后,它围绕上面创建的
JObject
创建了一个包装器
{
"properties": {
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
}
Json.NET 的行为如 Converting between JSON and XML:
中所述Single child text nodes are a value directly against an element, otherwise they are accessed via #text.
因为你的 <property>
节点有一个属性,值被放在 #text
属性.
但是为什么要用Json.NET把XElement
转换成ExpandoObject
呢?直接使用 LINQ 进行转换很简单 XML:
var doc = XDocument.Parse(xml);
IDictionary<string, object> properties = new ExpandoObject();
foreach (var property in doc.Root.Elements("property"))
properties.Add(property.Attribute("key").Value, property.Value);
dynamic d = new ExpandoObject();
d.properties = properties;
根据需要,结果为:
{
"properties": {
"EventId": "3300",
"source": "car",
"type": "omega",
"a341414": "any value",
"arandomstring_each_time_different": "any value"
}
}
演示 fiddle here.