Newtonsoft DeserializeXNode expands internal arrays incorrectly

烂漫一生 提交于 2020-02-24 06:49:51

问题


I have a JSON object like the following:

{
  "property1": "value1",
  "property2": "value2",
  "property3": ["value3","value4","value5"]
}

When I try to use DeserializeXNode to convert to XML, though, the array goes away.

<MyObj>
    <property1>value1</property1>
    <property2>value2</property2>
    <property3>value3</property3>
    <property3>value4</property3>
    <property3>value5</property3>
</MyObj>

This causes issue when I try to re-serialize back to the object, because I get a "cannot convert string to string[]" error. Moreover, when I try to parse the document, the duplicate properties are overwritten and only the last value remains. I've tried setting the third parameter of DeserializeXNode to true thinking that would mark the array properly, but that doesn't change anything.

By my understanding from the Newtonsoft docs, the XML should look more like:

<MyObj>
    <property1>value1</property1>
    <property2>value2</property2>
    <property3 type="array">
        <item>value3</item>
        <item>value4</item>
        <item>value5</item>
    </property3>
</MyObj>

What do I need to do to get the array to properly translate into the XML so that it will come back to JSON as an array?

For reference, here is the code I'm using (inherited, so I'm not sure if it makes sense):

ObjectToXML:

var json = JsonConvert.SerializeObject(o);
var xdoc = JsonConvert.DeserializeXNode(json, "MyObj", true);
return xdoc.ToString();

XMLToObject:

XDocument d = XDocument.Parse(xml, LoadOptions.None);
d.Descendants().ForEach(e => e.Attributes().Remove());
var json = JsonConvert.SerializeXNode(d);
json = json.Replace("\"?xml\":{\"@version\":\"1.0\",\"@encoding\":\"utf-16\"},\"MyObj\":{", "")
    .Replace("{\"MyObj\":", "")
    .Replace("}}", "}")
    .Replace("{\"anyType\":", "")
    .Replace("]}", "]");
return JsonConvert.DeserializeObject<T>(json);

And the object itself:

public class MyObj
{
    public string property1 { get; set; }
    public string property2 { get; set; }
    public string[] property3 { get; set; }
}

回答1:


I'm not sure where you've read this in the documentation. I've looked and I can't find anything that suggests the XML should look as you've suggested.

How this works is that multiple elements with the same name can be inferred to be an array. From the docs:

Multiple nodes with the same name at the same level are grouped together into an array.

And if there is only one element that originated from an array, then there is an overload you're using that instructs the serialiser to add an attribute indicating that element is an array. Your output would look something like this:

<MyObj xmlns:json="http://james.newtonking.com/projects/json">
  <property1>value1</property1>
  <property2>value2</property2>
  <property3 json:Array="true">value3</property3>
</MyObj>

And if you round trip it via XML using this code:

var asXml = JsonConvert.DeserializeXNode(json, "MyObj", writeArrayAttribute: true);
var asJson = JsonConvert.SerializeXNode(asXml, Formatting.Indented, omitRootObject: true);

You get exactly the same JSON back. So I can't find a problem here.

You can see the results in this fiddle, including deserialising to MyObj.



来源:https://stackoverflow.com/questions/43637298/newtonsoft-deserializexnode-expands-internal-arrays-incorrectly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!