Keep json:Array attribute when converting XML to JSON to XML

旧街凉风 提交于 2019-12-12 08:30:34

问题


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

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