将JSON序列化为对象。有些属性总是相同,有些不同

时间:2017-09-04 13:16:44

标签: c# json.net

我正在尝试构建一个用户可以上传json文件的函数。

json文件中的每一行都可以有不同的属性(即列)。 其中5个属性总是相同的,所以我希望将它们反序列化为一个对象。其余的属性必须进入字典或其他东西。

这是一个json示例:

[{
        "Projekt": "Bakker Bouw Service",
        "Ruimte": "Hoofdgebouw",
        "Apparaat": {
            "project": "Bosboom001",
            "versie": "812"
        },
        "Apparaat naam": "",
        "Status": "Goedgekeurd",
        "Testname1": "",
        "Testname3": "2000-01-04T10:37:00+01:00",
        "Testname7": "2001-01-03T00:00:00+01:00"
    }, {
        "Projekt": "Bakker Bouw Service",
        "Ruimte": "Hoofdgebouw",
        "Apparaat": {
            "project": "Vlaams003",
            "versie": "713"
        },
        "Apparaat naam": "",
        "Status": "Goedgekeurd",
        "Testname1": "Slecht",
        "Testname7": "2000-01-04T10:37:00+01:00",
        "Testname9": "2001-01-03T00:00:00+01:00",
        "Testname16": "18MOhm",
        "Testname23": "OK"
    }, {
        "Projekt": "Bakker Bouw Service",
        "Ruimte": "Hoofdgebouw",
        "Apparaat": {
            "project": "Vlaams017",
            "versie": "73"
        },
        "Apparaat naam": "GDR34Z5",
        "Status": "Afgekeurd",
        "Testname7": "2000-01-04T10:37:00+01:00",
        "Testname10": "0,012mA",
        "Testname16": "200MOhm",
        "Testname23": "200MOhm",
        "Testname25": "Afgekeurd",
        "Testname31": "0,01mA"
    }
]

以下是要反序列化的课程:

public class KeuringRegel
{
    public string Projekt { get; set; }
    public string Ruimte { get; set; }
    public Apparaat Apparaat { get; set; }
    [JsonProperty(PropertyName = "Apparaat naam")]
    public string Apparaatnaam { get; set; }
    public string Status { get; set; }
    public Dictionary<string, object> testNames { get; set; }
}

public class Apparaat
{
    public string project { get; set; }
    public string versie { get; set; }
}

这是控制器

public IActionResult Upload(IFormFile file)
    {
        string fileContent = null;
        using (var reader = new StreamReader(file.OpenReadStream()))
        {
            fileContent = reader.ReadToEnd();
        }
        List<KeuringRegel> keuringRegelList = JsonConvert.DeserializeObject<List<KeuringRegel>>(fileContent);
        //More stuff here
    }

json成功反序列化,但testNames值始终为null。我理解为什么,因为Json文件中没有testNames属性。但是,我如何实现我想要的?我不是Json专家。

2 个答案:

答案 0 :(得分:3)

一种方法可以做到这一点,假设只有 testNameNNNN条目作为补充值,就是使用JsonExtensionDataAttribute这样:

public class KeuringRegel
{
    public string Projekt { get; set; }
    public string Ruimte { get; set; }
    public Apparaat Apparaat { get; set; }
    [JsonProperty(PropertyName = "Apparaat naam")]
    public string Apparaatnaam { get; set; }
    public string Status { get; set; }
    [JsonExtensionData()]
    public Dictionary<string, object> testNames { get; set; }
}

这将为您提供不属于其他属性的值:

enter image description here

这是一个“钝器”,但你总是可以对返回的KeuringRegel实例执行一些后处理,以从testNames中删除任何错误的条目(即与模式不匹配的事物{{ 1}})。

如果您的JSON 包含与因此包含的模式testNameNNNN不匹配的内容,则可以为testNameNNNN属性实现自定义类:< / p>

testNames

这将检查添加到public class KeuringRegel { public string Projekt { get; set; } public string Ruimte { get; set; } public Apparaat Apparaat { get; set; } [JsonProperty(PropertyName = "Apparaat naam")] public string Apparaatnaam { get; set; } public string Status { get; set; } [JsonExtensionData()] public TestNames testNames { get; set; } } public class TestNames : Dictionary<string, object> { public new void Add(string key, object value) { if (key.StartsWith("testname", StringComparison.OrdinalIgnoreCase)) { base.Add(key, value); } } } 字典的每个项目并阻止其添加(如在我的评论中我在testNames的JSON中有一个项目)它与图案。

答案 1 :(得分:0)

这里你是完整的例子

internal class Program
    {
        private static void Main(string[] args)
        {
            var str = @"[{
        ""Projekt"": ""Bakker Bouw Service"",
        ""Ruimte"": ""Hoofdgebouw"",
        ""Apparaat"": {
            ""project"": ""Bosboom001"",
            ""versie"": ""812""
        },
        ""Apparaat naam"": """",
        ""Status"": ""Goedgekeurd"",
        ""Testname1"": """",
        ""Testname3"": ""2000-01-04T10:37:00+01:00"",
        ""Testname7"": ""2001-01-03T00:00:00+01:00""
    }, {
        ""Projekt"": ""Bakker Bouw Service"",
        ""Ruimte"": ""Hoofdgebouw"",
        ""Apparaat"": {
            ""project"": ""Vlaams003"",
            ""versie"": ""713""
        },
        ""Apparaat naam"": """",
        ""Status"": ""Goedgekeurd"",
        ""Testname1"": ""Slecht"",
        ""Testname7"": ""2000-01-04T10:37:00+01:00"",
        ""Testname9"": ""2001-01-03T00:00:00+01:00"",
        ""Testname16"": ""18MOhm"",
        ""Testname23"": ""OK""
    }, {
        ""Projekt"": ""Bakker Bouw Service"",
        ""Ruimte"": ""Hoofdgebouw"",
        ""Apparaat"": {
            ""project"": ""Vlaams017"",
            ""versie"": ""73""
        },
        ""Apparaat naam"": ""GDR34Z5"",
        ""Status"": ""Afgekeurd"",
        ""Testname7"": ""2000-01-04T10:37:00+01:00"",
        ""Testname10"": ""0,012mA"",
        ""Testname16"": ""200MOhm"",
        ""Testname23"": ""200MOhm"",
        ""Testname25"": ""Afgekeurd"",
        ""Testname31"": ""0,01mA""
    }
]";

            var sw = Stopwatch.StartNew();

            var result = Mapper.Map(str);


            sw.Stop();
            Console.WriteLine($"Deserialized at {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} tiks)");
        }

        public static class Mapper
        {
            static Mapper()
            {
                List<string> names = new List<string>();
                IEnumerable<PropertyInfo> p = typeof(KeuringRegel).GetProperties().Where(c => c.CanRead && c.CanWrite);
                foreach (var propertyInfo in p)
                {
                    var attr = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>();
                    names.Add(attr != null ? attr.PropertyName : propertyInfo.Name);
                }

                Properties = names.ToArray();
            }


            private static string[] Properties { get; }



            public static KeuringRegel[] Map(string str)
            {
                var keuringRegels = JsonConvert.DeserializeObject<KeuringRegel[]>(str);
                var objs = JsonConvert.DeserializeObject(str) as IEnumerable;
                var objectList = new List<JObject>();
                foreach (JObject obj in objs)
                    objectList.Add(obj);

                for (var i = 0; i < keuringRegels.Length; i++)
                {
                    keuringRegels[i].testNames = new Dictionary<string, object>();
                    foreach (var p in objectList[i].Children().OfType<JProperty>().Where(c => !Properties.Contains(c.Name)).ToArray())
                        keuringRegels[i].testNames.Add(p.Name, p.Value);
                }

                return keuringRegels;
            }
        }


        public class KeuringRegel
        {
            public string Projekt { get; set; }
            public string Ruimte { get; set; }
            public Apparaat Apparaat { get; set; }

            [JsonProperty(PropertyName = "Apparaat naam")]
            public string Apparaatnaam { get; set; }

            public string Status { get; set; }
            public Dictionary<string, object> testNames { get; set; }
        }

        public class Apparaat
        {
            public string project { get; set; }
            public string versie { get; set; }
        }
    }