【问题标题】:C# parsing JSON array overwrites values on the listC# 解析 JSON 数组会覆盖列表中的值
【发布时间】:2018-06-20 13:01:43
【问题描述】:

我在将 json 文件反序列化到我的班级时遇到问题。 Json 文件如下所示:

    { 
    "DataFile": {
        "header":{
            "version": "123",
            "date": "01.01.01",         
        },
        "customer": {
            "fID": "12-35-58",
            "nameCust": "CompanyName",
            "adressCust":{
                "zip": "0000",
                "city": "Foovile",
                "streetNr": "1",
                "post": "FoovilePost",
                "street": "DunnoStr",
            },
        },
        "content": [
                {
                    "invoice":{
                        "DFID":"538",
                    },
                    "invoice":{
                        "DFID":"500",
                    },
                    "invoice":{
                        "DFID":"550",
                    },
                    "receipt":{
                        "DFID":"758",
                    },
                    "receipt":{
                        "DFID":"75",
                    },
                }               
            ],

    }
    }

内容数组反序列化之前的所有内容都很好,所以为了清楚起见,我将跳过部分课程。相关位如下所示:

class DFFile
{
    public DF Df { get; set; }
}

class DF
{
    public Header header { get; set; }
    public Customer customer { get; set; }
    public List<DFContent> content { get; set; }
}
class DFContent
{
    public Invoice invoice { get; set; }
    public Receipt receipt { get; set; }
}
class Invoice
{
    public int DFID { get; set; }
}
class Receipt
{
    public int DFID { get; set; }
}

我像这样反序列化为 DFFile 实例:

DFFile sample = JsonConvert.DeserializeObject<DFFile>(json);

我的问题是它反序列化时没有错误,但 sample.DF.content 只有一个元素,其中包含发票和收据以及每种类型的最后一个 ID。我正在寻找的结果是 json 内容数组的每个项目都有新元素的列表。 我可以改变我的班级,但是这个 json 的构建方式是一成不变的,对此无能为力,必须处理它。

有什么方法可以阻止它更改内容的最后一个元素并添加新元素吗?

【问题讨论】:

  • content 有一个包含一个对象的数组,并且您输入的键是相同的,因此它们将被覆盖。
  • 你能改变你的班级结构吗?
  • @Jamie,是的,这就是这里的问题。我实际上还没有正确的 JSON 文件,我只有 JSON Schema,所以为了测试我创建了自己的测试 json 并在那里搞砸了。感谢您的快速回答

标签: c# json serialization arraylist


【解决方案1】:

由于您无法更改 JSON,因此我假设您可以更改类结构。

请考虑这些课程:

class DF
{
    // Other properties...
    [JsonConverter(typeof(FunnyListConverter))]
    public List<Content> content { get; set; }
}

class Content
{
    public int DFID { get; set; }
}

class Invoice : Content
{
}
class Receipt : Content
{
}

这里是 FunnyListConverter:

public class FunnyListConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var content = new List<Content>();
        var currentType = "";
        Invoice currentInvoice = null;
        Receipt currentReceipt = null;
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndArray)
            {
                break;
            }
            if (reader.Value?.ToString() == "invoice")
            {
                currentInvoice = new Invoice();
                currentType = "invoice";
            }
            if (reader.Value?.ToString() == "receipt")
            {
                currentReceipt = new Receipt();
                currentType = "receipt";
            }
            if (reader.Path.Contains("DFID") && reader.Value?.ToString() != "DFID")
            {
                switch (currentType)
                {
                    case "invoice":
                        currentInvoice.DFID = int.Parse(reader.Value.ToString());
                        content.Add(currentInvoice);
                        currentInvoice = null;
                        break;
                    case "receipt":
                        currentReceipt.DFID = int.Parse(reader.Value.ToString());
                        content.Add(currentReceipt);
                        currentReceipt = null;
                        break;
                }
            }
        }
        return content;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
          }
            if (reader.Value?.ToString() == "receipt")
            {
                currentReceipt = new Receipt();
                currentType = "receipt";
            }
            if (reader.Path.Contains("DFID") && reader.Value?.ToString() != "DFID")
            {
                switch (currentType)
                {
                    case "invoice":
                        currentInvoice.DFID = int.Parse(reader.Value.ToString());
                        content.Add(currentInvoice);
                        currentInvoice = null;
                        break;
                    case "receipt":
                        currentReceipt.DFID = int.Parse(reader.Value.ToString());
                        content.Add(currentReceipt);
                        currentReceipt = null;
                        break;
                }
            }
        }
        return content;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

【讨论】:

  • 感谢您的回答,这是我正在尝试但无法使其发挥作用的方法。我将保留您的答案以供将来参考,因为我是 JSON 反序列化的新手。但实际的问题是我的测试 json 文件,因为我现在只有 json 模式,我创建了自己的用于测试并在数组中搞砸了 {}。再次抱歉占用您的时间,并感谢您的快速回答。 +1
【解决方案2】:

您的内容设置为包含一个数组,但其中只有一项具有三个发票和两个收据值。假设您希望您的 DFContent 保存收据或发票,请将其更改为如下所示:

 "content": [
                {"invoice":{
                        "DFID":"538",
                }},
                {"invoice":{
                        "DFID":"500",
                }},
                {"invoice":{
                        "DFID":"550",
                }},
                {"receipt":{
                        "DFID":"758",
                }},
                {"receipt":{
                        "DFID":"75",
                }}               
            ],

【讨论】:

    猜你喜欢
    • 2011-09-28
    • 1970-01-01
    • 2018-08-26
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多