将XML转换为JSON,然后反序列化为对象

时间:2017-07-03 11:24:56

标签: c# json xml json.net

我正在使用.Net Framework 4.7和JSON.NET 10.0.2开发ASP.NET MVC应用程序。

我想加载一个xml文档,将其转换为JSON,然后反序列化为object。我想这样做是因为我想使用JSON文件和XML文件。

这是我想用文件创建的类:

public class ProductionOrderFile
{
    public string ProductionOrderName { get; set; }
    public string ProductCode { get; set; }
    public List<Batch> Batches { get; set; }
    public List<AggregationLevelConfiguration> Levels { get; set; }
    public List<VariableData> VariableData { get; set; }
}

这是反序列化到对象的类:

private ProductionOrderFile ParseProductionOrderFile(Stream inputStream)
{
    var serializer = new JsonSerializer();
    XmlDocument doc = new XmlDocument();
    doc.Load(inputStream);

    string jsonText = JsonConvert.SerializeXmlNode(doc);

    return JsonConvert.DeserializeObject<ProductionOrderFile>(jsonText);
}

这是XML文档:

<ProductionOrderFile>
    <ProductionOrderName>"ProOrd_Xml_001"</ProductionOrderName>
    <ProductCode>Pro_EU_001</ProductCode>
    <Batches>
        <Name>Lote_Xml_01</Name>
    </Batches>
    <Levels>
        <Id>1</Id>
        <Name>Nivel_1</Name>
        <PkgRatio>120</PkgRatio>
    </Levels>
    <Levels>
        <Id>2</Id>
        <Name>Nivel_2</Name>
        <PkgRatio>1</PkgRatio>
    </Levels>
    <VariableData>
        <VariableDataId>01</VariableDataId>
        <LevelId>1</LevelId>
        <Value>Pro_EU_001</Value>
    </VariableData>
    <VariableData>
        <VariableDataId>20</VariableDataId>
        <LevelId>1</LevelId>
        <Value>Lote_Xml_01</Value>
    </VariableData>
    <VariableData>
        <VariableDataId>11</VariableDataId>
        <LevelId>1</LevelId>
        <Value>170101</Value>
    </VariableData>
    <VariableData>
        <VariableDataId>17</VariableDataId>
        <LevelId>1</LevelId>
        <Value>210101</Value>
    </VariableData>
    <VariableData>
        <VariableDataId>21</VariableDataId>
        <LevelId>1</LevelId>
        <Value>####################</Value>
    </VariableData>
</ProductionOrderFile>

这是jsonText var内容:

{
    "ProductionOrderFile": {
        "ProductionOrderName": "\"ProOrd_Xml_001\"",
        "ProductCode": "Pro_EU_001",
        "Batches": {
            "Name": "Lote_Xml_01"
        },
        "Levels": [{
            "Id": "1",
            "Name": "Nivel_1",
            "PkgRatio": "120"
        }, {
            "Id": "2",
            "Name": "Nivel_2",
            "PkgRatio": "1"
        }],
        "VariableData": [{
            "VariableDataId": "01",
            "LevelId": "1",
            "Value": "Pro_EU_001"
        }, {
            "VariableDataId": "20",
            "LevelId": "1",
            "Value": "Lote_Xml_01"
        }, {
            "VariableDataId": "11",
            "LevelId": "1",
            "Value": "170101"
        }, {
            "VariableDataId": "17",
            "LevelId": "1",
            "Value": "210101"
        }, {
            "VariableDataId": "21",
            "LevelId": "1",
            "Value": "####################"
        }]
    }
}

但是这个return JsonConvert.DeserializeObject<ProductionOrderFile>(jsonText);返回ProductionOrderFile的实例,其所有属性都为null。

问题可能是XML文档没有正确的格式。

XML文档的格式是否正确? 我做错了什么?

1 个答案:

答案 0 :(得分:1)

反序列化XML的最简单方法是使用XmlSerializer一步完成。您可以通过使用[XmlElement]标记List<T>属性来指示它们应序列化为没有外部容器元素的重复元素的集合来执行此操作:

public class ProductionOrderFile
{
    public string ProductionOrderName { get; set; }
    public string ProductCode { get; set; }
    [System.Xml.Serialization.XmlElement]
    public List<Batch> Batches { get; set; }
    [System.Xml.Serialization.XmlElement]
    public List<AggregationLevelConfiguration> Levels { get; set; }
    [System.Xml.Serialization.XmlElement]
    public List<VariableData> VariableData { get; set; }
}

然后做:

private ProductionOrderFile ParseProductionOrderFile(Stream inputStream)
{
    var serializer = new XmlSerializer(typeof(ProductionOrderFile));
    return (ProductionOrderFile)serializer.Deserialize(inputStream);
}

示例fiddle #1

话虽如此,如果您坚持使用中间XmlDocument进行两步反序列化过程,则需要按如下方式修改代码:

  1. 在创建中间jsonText时使用JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true)省略根元素。

    这将删除"ProductionOrderFile": { ... }中未显示的根ProductionOrderFile属性,并将嵌套属性冒充到最高级别。

  2. 按照Convert XML to JSON and force array中的说明强制将<Batches><Levels><VariableData>元素转换为JSON作为数组。

  3. 因此您的代码变为:

    private ProductionOrderFile ParseProductionOrderFile(Stream inputStream)
    {
        var serializer = new JsonSerializer();
        XmlDocument doc = new XmlDocument();
        doc.Load(inputStream);
    
        foreach (var xPath in new [] { "//Batches", "//Levels", "//VariableData" })
        {
            foreach (var node in doc.SelectNodes(xPath).Cast<XmlElement>())
            {
                node.SetAttribute("xmlns:json", "http://james.newtonking.com/projects/json");
                node.SetAttribute("Array", "http://james.newtonking.com/projects/json", XmlConvert.ToString(true));
            }
        }
    
        string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true);
    
        return JsonConvert.DeserializeObject<ProductionOrderFile>(jsonText);
    }
    

    示例fiddle #2