JSON属性生成为节点

3

我需要将一个传入的json文件转换为XML格式。

我正在使用以下代码来实现这个要求。我正在使用Newtonsoft Json Converter。

 XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);

输入文件为:

{"menu": {   "id": "file",   "value": "File",   "popup": {     "menuitem": [       {"value": "New", "onclick": "CreateNewDoc()"},       {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"}  ]  }}}

我得到的输出是
<menu><id>file</id><value>File</value><popup><menuitem><value>New</value><onclick>CreateNewDoc()</onclick></menuitem><menuitem><value>Open</value><onclick>OpenDoc()</onclick></menuitem><menuitem><value>Close</value><onclick>CloseDoc()</onclick></menuitem></popup></menu>

这里的属性被生成为节点。

提前感谢。

2个回答

2

在属性名前应添加@

像这样:

{"menu": { "@id": "file", "@value": "File", "popup": { "menuitem": [ {"@value": "New", "@onclick": "CreateNewDoc()"}, {"@value": "Open", "@onclick": "OpenDoc()"}, {"@value": "Close", "@onclick": "CloseDoc()"} ] }}}

这将创建以下XML代码:
<menu id="file" value="File">
    <popup>
        <menuitem value="New" onclick="CreateNewDoc()" />
        <menuitem value="Open" onclick="OpenDoc()" />
        <menuitem value="Close" onclick="CloseDoc()" />
    </popup>
</menu>

如果您无法控制JSON,则可以在将其转换为XML之前以编程方式修改它,如下所示:

json = json.Replace("id", "@id").Replace("value", "@value").Replace("onclick", "@onclick");

或者您可以使用XSLT在转换后转换XML。


谢谢回复...但我的输入来自一个json文件,它会有几MB大小,所以我无法手动更改。还有其他方法吗? - Kokirala Sudheer
你知道所有属性的完整列表吗?你可以通过编程方式替换它们:json = json.Replace("id", "@id").Replace("value", "@value").Replace("onclick", "@onclick"); - Vova
1
@KokiralaSudheer 这取决于你的XML是否有已知的模式。如果它的模式像你的示例那样被定义并且简单,那么有一些选项(请参见更新的答案),但是如果它可以是任何XML,则我无法想到一种通用的方法来处理它。 - Vova

2

来自JSON和XML转换

转换规则

  • 属性以@为前缀,应位于对象的开头。

因此,您可以使用Linq to JSON修改所有具有原始值的JSON属性,并在它们的名称前面添加@字符。请注意,由于您的文件将是“以MB为单位”,因此应避免将其加载到临时字符串中,而应直接流式传输文件内容

        // Load the JObject directly from a file
        using (var streamReader = File.OpenText(fileName))
        using (var jsonReader = new JsonTextReader(streamReader))
        {
            obj = JObject.Load(jsonReader);
        }

        // Rename all properties with primitive values (string, number, boolean, null) to begin with "@"
        foreach (var o in obj.Descendants().OfType<JObject>())
        {
            // Attributes must appear first in the JObject's property list.
            int insertIndex = 0;
            foreach (var property in o.Properties().Where((p => p.Value is JValue && !p.Name.StartsWith("@"))).ToList())
            {
                property.Remove();
                ((IList<JToken>)o).Insert(insertIndex++, new JProperty("@" + property.Name, property.Value));
            }
        }

        // Convert to XmlDocument
        XmlDocument doc;
        using (var reader = obj.CreateReader())
        {
            doc = (XmlDocument)JsonExtensions.DeserializeXmlNode(reader);
        }

使用辅助方法:

public static class JsonExtensions
{
    public static XmlDocument DeserializeXmlNode(JsonReader reader)
    {
        return DeserializeXmlNode(reader, null, false);
    }

    public static XmlDocument DeserializeXmlNode(JsonReader reader, string deserializeRootElementName, bool writeArrayAttribute)
    {
        var converter = new Newtonsoft.Json.Converters.XmlNodeConverter() { DeserializeRootElementName = deserializeRootElementName, WriteArrayAttribute = writeArrayAttribute };
        var jsonSerializer = JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new JsonConverter[] { converter } });
        return (XmlDocument)jsonSerializer.Deserialize(reader, typeof(XmlDocument));
    }
}

这将产生如下输出:
<menu id="file" value="File">
  <popup>
    <menuitem value="New" onclick="CreateNewDoc()" />
    <menuitem value="Open" onclick="OpenDoc()" />
    <menuitem value="Close" onclick="CloseDoc()" />
  </popup>
</menu>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接