C#问题:将XML反序列化为JSON数组

huangapple go评论110阅读模式
英文:

C# Problem deserialize XML into JSON array

问题

我有以下的XML:

<table>
    <name>Table 1</name>
    <headers>
        <header>Header 1</header>
        <header>Header 2</header>
    </headers>
    <data>
        <row>
            <row_item>Item 1</row_item>
            <row_item>Item 2</row_item>
        </row>
        <row>
            <row_item>Item 3</row_item>
            <row_item>Item 4</row_item>
        </row>
    </data>
</table>

现在我可以使用内置的XmlSerializer类轻松反序列化它,使用以下类:

[JsonObject("table")]
[XmlRoot("table")]
public class Table
{
    [JsonProperty("name")]
    [XmlElement("name")]
    public string Name { get; set; }

    [JsonProperty("headers")]
    [XmlArray("headers"), XmlArrayItem("header")]
    public List<string> Headers { get; set; } = new List<string>();

    [JsonProperty("data")]
    [XmlArray("data"), XmlArrayItem("row")]
    public List<DataRow> Data { get; set; } = new List<DataRow>();
}

public class DataRow
{
    [XmlElement("row_item")]
    public List<string> DataRowItems { get; set; }
}

现在我需要将其转换为JSON,我正在使用Newtonsoft来完成这个任务,但我面临的问题是当前的类结构会将 "DataRowItems" 添加到JSON 中。

{
    "table": [
        {
            "data": [
                {
                    "DataRowItems": [
                        "Item 1",
                        "Item 2"
                    ]
                },
                {
                    "DataRowItems": [
                        "Item 3",
                        "Item 4"
                    ]
                }
            ],
            "headers": [
                "Item 1",
                "Item 2",
                "Item 3"
            ],
            "name": "Some text"
        }
    ]
}

而我需要将 "data" 元素作为数组的数组发送,就像这样:

{
    "table": [
        {
            "data": [
                ["Item 1", "Item 2", "Item 3"],
                ["Item 4", "Item 5", "Item 6"]
            ],
            "headers": ["Column 1", "Column 2", "Column 3"],
            "name": "Some text"
        }
    ]
}

如何实现这一点呢?我已经尝试了各种XML和JSON属性,但似乎无法使其工作。我还尝试使用 List<List<string>> 而不是 List<DataRow>,它可以正确创建JSON,但XML 无法反序列化。

英文:

I have the following XML

&lt;table&gt;
	&lt;name&gt;Table 1&lt;/name&gt;
	&lt;headers&gt;
		&lt;header&gt;Header 1&lt;/header&gt;
		&lt;header&gt;Header 2&lt;/header&gt;
	&lt;/headers&gt;
	&lt;data&gt;
		&lt;row&gt;
			&lt;row_item&gt;Item 1&lt;/row_item&gt;
			&lt;row_item&gt;Item 2&lt;/row_item&gt;
		&lt;/row&gt;
		&lt;row&gt;
			&lt;row_item&gt;Item 3&lt;/row_item&gt;
			&lt;row_item&gt;Item 4&lt;/row_item&gt;
		&lt;/row&gt;
	&lt;/data&gt;
&lt;/table&gt;

Now I can deserialize this easy enough using the built in XmlSerializer class using this class.

[JsonObject(&quot;table&quot;)]
[XmlRoot(&quot;table&quot;)]
public class Table
{
    [JsonProperty(&quot;name&quot;)]
    [XmlElement(&quot;name&quot;)]
    public string Name { get; set; }

    [JsonProperty(&quot;headers&quot;)]
    [XmlArray(&quot;headers&quot;), XmlArrayItem(&quot;header&quot;)]
    public List&lt;string&gt; Headers { get; set; } = new List&lt;string&gt;();

    [JsonProperty(&quot;data&quot;)]
    [XmlArray(&quot;data&quot;), XmlArrayItem(&quot;row&quot;)]
    public List&lt;DataRow&gt; Data { get; set; } = new List&lt;DataRow&gt;();

}

public class DataRow
{
    [XmlElement(&quot;row_item&quot;)]
    public List&lt;string&gt; DataRowItems { get; set; }
}

Now I need to convert this to JSON, I am using Newtonsoft to do this but the problem I am facing is that the current class structure adds "DataRowItems" to the JSON.

{
	&quot;table&quot;: [
		{
			&quot;data&quot;: [
				{
					&quot;DataRowItems&quot;: [
						&quot;Item 1&quot;,
						&quot;Item 2&quot;
					]
				},
				{
					&quot;DataRowItems&quot;: [
						&quot;Item 3&quot;,
						&quot;Item 4&quot;
					]
				}
			],
			&quot;headers&quot;: [
				&quot;Item 1&quot;,
				&quot;Item 2&quot;,
				&quot;Item 3&quot;
			],
			&quot;name&quot;: &quot;Some text&quot;
		}
	]
}

Where as I need to send the data element as an array of array, like this.

{
  &quot;table&quot;: [
	{
	  &quot;data&quot;: [
		[&quot;Item 1&quot;, &quot;Item 2&quot;, &quot;Item 3&quot;],
		[&quot;Item 4&quot;, &quot;Item 5&quot;, &quot;Item 6&quot;]
	  ],
	  &quot;headers&quot;: [&quot;Column 1&quot;, &quot;Column 2&quot;, &quot;Column 3&quot;],
	  &quot;name&quot;: &quot;Some text&quot;
	}
  ]
}

How can I achieve this? I have been trying with various XML and JSON attributes but can't seem to get it to work. I have also tried using List<List<string>> instead of List<DataRow> which creates the JSON correctly, but the XML fails to deseralize.

答案1

得分: 1

移除 DataRow 并以嵌套列表的方式进行如下操作:

{
   "name":"aaa",
   "headers":["H1","H2","H3"],
   "data":[
      ["i1","i2"],
      ["i3","i4"]
   ]
}
英文:

Remove DataRow and put a nested List this way:

    [JsonObject(&quot;table&quot;)]
    [XmlRoot(&quot;table&quot;)]
    public class Table
    {
        [JsonProperty(&quot;name&quot;)]
        [XmlElement(&quot;name&quot;)]
        public string Name { get; set; }

        [JsonProperty(&quot;headers&quot;)]
        [XmlArray(&quot;headers&quot;), XmlArrayItem(&quot;header&quot;)]
        public List&lt;string&gt; Headers { get; set; } = new List&lt;string&gt;();

        [JsonProperty(&quot;data&quot;)]
        [XmlArray(&quot;data&quot;), XmlArrayItem(&quot;row&quot;)]
        public List&lt;List&lt;string&gt;&gt; Data { get; set; } = new List&lt;List&lt;string&gt;&gt;();

    }

I obtained:
{"name":"aaa","headers":["H1","H2","H3"],"data":[["i1","i2"],["i3","i4"]]}

答案2

得分: 1

以下是代码的翻译部分:

你可以尝试这个,你不需要任何自定义类
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);

var json = JsonConvert.SerializeXmlNode(xmlDoc, Newtonsoft.Json.Formatting.None, true);
var jObj = JObject.Parse(json);

jObj["headers"] = jObj["headers"]["header"];
jObj["data"] = new JArray(jObj["data"]["row"].Select(x => x["row_item"]));
json = jObj.ToString();

输出

{
  "name": "Table 1",
  "headers": [
    "Header 1",
    "Header 2"
  ],
  "data": [
    [
      "Item 1",
      "Item 2"
    ],
    [
      "Item 3",
      "Item 4"
    ]
  ]
}

或者,如果你想要C#对象

DataClass data = jObj.ToObject<DataClass>();

public partial class DataClass
{
	[JsonProperty("name")]
	public string Name { get; set; }

	[JsonProperty("headers")]
	public List<string> Headers { get; set; }

	[JsonProperty("data")]
	public List<List<string>> Data { get; set; }
}
英文:

you can try this, you don't need any custom classes

	XmlDocument xmlDoc = new XmlDocument();
	xmlDoc.LoadXml(xml);
	
	var json = JsonConvert.SerializeXmlNode(xmlDoc, Newtonsoft.Json.Formatting.None, true);
	var jObj = JObject.Parse(json);

	jObj[&quot;headers&quot;] = jObj[&quot;headers&quot;][&quot;header&quot;];
	jObj[&quot;data&quot;] = new JArray(jObj[&quot;data&quot;][&quot;row&quot;].Select(x =&gt; x[&quot;row_item&quot;]));
	json=jObj.ToString();

output

{
  &quot;name&quot;: &quot;Table 1&quot;,
  &quot;headers&quot;: [
    &quot;Header 1&quot;,
    &quot;Header 2&quot;
  ],
  &quot;data&quot;: [
    [
      &quot;Item 1&quot;,
      &quot;Item 2&quot;
    ],
    [
      &quot;Item 3&quot;,
      &quot;Item 4&quot;
    ]
  ]
}

or if you want c# object

DataClass data = jObj.ToObject&lt;DataClass&gt;();

public partial class DataClass
{
	[JsonProperty(&quot;name&quot;)]
	public string Name { get; set; }

	[JsonProperty(&quot;headers&quot;)]
	public List&lt;string&gt; Headers { get; set; }

	[JsonProperty(&quot;data&quot;)]
	public List&lt;List&lt;string&gt;&gt; Data { get; set; }
}


</details>



# 答案3
**得分**: -1

谢谢大家的建议,这是我用来使其正常工作的类中属性的最终设置。

```csharp
[JsonProperty("data")]
[XmlArray("data")]
[XmlArrayItem("row")]
[XmlArrayItem("row_item", NestingLevel = 1)]
public List<List<string>> Data { get; set; } = new List<List<string>>();
```

`NestingLevel` 项是使 `row_item` 正确反序列化的关键。

<details>
<summary>英文:</summary>

Thank you everyone for the suggestions, this was the final setup for property in the class that I used to get it working.

        [JsonProperty(&quot;data&quot;)]
        [XmlArray(&quot;data&quot;)]
        [XmlArrayItem(&quot;row&quot;)]
        [XmlArrayItem(&quot;row_item&quot;, NestingLevel = 1)]
        public List&lt;List&lt;string&gt;&gt; Data { get; set; } = new List&lt;List&lt;string&gt;&gt;();

The `NestingLevel` item was the key to getting `row_item` to deserialize correctly.

</details>



huangapple
  • 本文由 发表于 2023年3月7日 23:13:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定