问题
I have a piece of XML that looks like
<person xmlns:json='http://james.newtonking.com/projects/json' id='1'>
<name>Alan</name>
<url>http://www.google.com</url>
<role json:Array='true'>Admin</role>
</person>
When I try to serialize it to json string json = JsonConvert.SerializeXmlNode(xml);
it ignores namespaces
{
"person": {
"@id": "1",
"name": "Alan",
"url": "http://www.google.com",
"role": [
"Admin"
]
}
}
and when I deserialize it back to xml XmlDocument xml = JsonConvert.DeserializeXmlNode(json)
, I get the following:
<person id='1'>
<name>Alan</name>
<url>http://www.google.com</url>
<role>Admin</role>
</person>
How can I keep the json:Array
attributes?
回答1:
There is overload of DeserializeXmlNode
which accepts boolean flag named writeArrayAttribute
. That's what you need:
XmlDocument xml = JsonConvert.DeserializeXmlNode(json, null, true);
Produces:
<person id="1">
<name>Alan</name>
<url>http://www.google.com</url>
<role xmlns:json="http://james.newtonking.com/projects/json" json:Array="true">Admin</role>
</person>
Which is semantically identical to original xml.
回答2:
The XMl to JSon loses all the information of any attributes that have ':' (colon) in their name. Which is why 'id' get serialised to @id but 'xmlns:json' is lost in translation.
If you have access to the raw XML then I will suggest you replace the colons(:) by hyphens(-). In this case, the XML will be:
<person xmlns-json='http://james.newtonking.com/projects/json' id='1'>
<name>Alan</name>
<url>http://www.google.com</url>
<role json-Array='true'>Admin</role>
</person>
I have checked that this serialises and de-serialises to the same input and output.
var xmlString = @"<person xmlns-json='http://james.newtonking.com/projects/json' id='1'><name>Alan</name><url>http://www.google.com</url><role json-Array='true'>Admin</role></person>";
var xml = new XmlDocument();
xml.LoadXml(xmlString);
var json = JsonConvert.SerializeXmlNode(xml);
var xmlDeserialized = JsonConvert.DeserializeXmlNode(json);
xmlDeserialized.Should().NotBeNull();
xmlDeserialized.ShouldBeEquivalentTo(xml); //All good
回答3:
Maybe the problem is not how you serialize the xml node. Verify how you read your xml file before serializing it. Can you show us?
回答4:
this may be another approach custom json converter a bit long but I think it's more useful
Code
public class CustomXmlToJsonConverter : JsonConverter
{
private readonly Type[] _types;
public CustomXmlToJsonConverter(params Type[] types)
{
_types = types;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();
o.AddFirst(new JProperty("Keys", new JArray(propertyNames)));
o.WriteTo(writer);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}
public override bool CanRead
{
get { return false; }
}
public override bool CanConvert(Type objectType)
{
return _types.Any(t => t == objectType);
}
}
Usage
string json = JsonConvert.SerializeObject(root,Formatting.Indented,new CustomXmlToJsonConverter(typeof(XElement)));
Result
{
"Keys": [
"person"
],
"person": {
"@json": "http://james.newtonking.com/projects/json",
"@id": "1",
"name": "Alan",
"url": "http://www.google.com",
"role": {
"@Array": "true",
"#text": "Admin"
}
}
}
Sample Data
XNamespace jsonPrefix1 = "xmlns";
XNamespace jsonPrefix2 = "json";
XElement root = new XElement("person",
new XAttribute(jsonPrefix1 + "json", "http://james.newtonking.com/projects/json"),
new XAttribute("id","1"),
new XElement("name", "Alan"), new XElement("url", "http://www.google.com"),
new XElement("role" ,"Admin", new XAttribute(jsonPrefix2 + "Array", "true"))
);
来源:https://stackoverflow.com/questions/48763666/keep-jsonarray-attribute-when-converting-xml-to-json-to-xml