2017-09-04 33 views
2

我想建立一个用户可以上传json文件的功能。Dserialise JSON到对象。一些属性总是相同的,一些不同

json文件中的每一行都可以有不同的nr属性(即列)。 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" 
    } 
] 

下面是deserialze到类:

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值始终为空。我明白为什么,因为Json文件中没有testNames属性。但是,我如何实现我想要的?我不是Json专家。你能做到这一点,假设有只有testNameNNNN条目作为补充值

+0

这哪里是JSON建? –

+0

https://codebeautify.org/jsonviewer –

+1

他们可能是想问你是否可以改变JSON的格式,或者必须按原样解析它。 – CodeCaster

回答

3

的一种方法,是使用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

这是一个有点“钝器”,但你总是可以执行一些,生产工程过程后g在返回的KeuringRegel实例上删除任何来自testNames的错误条目(即,与模式testNameNNNN不匹配的东西)。

如果你的JSON 确实包含的东西不匹配,因此它会得到包括模式testNameNNNN,你可以实现的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 "badgerBadgetCatCat": 3)它不符合模式。

+1

我正在寻找一个自定义的JsonConverter,但很快就放弃了。这是最实用的解决方案。 JSON.NET将从类属性反序列化,而不是从JSON反序列化,所以转换器永远不会看到'TestnameNN'令牌。 – CodeCaster

+1

优秀的解决方案!谢谢!这个解决方案有没有优点和缺点?这是推荐的做事方式吗?更改JSON格式更好吗?也许是一个很好的示例文档或什么东西的链接 –

+1

@Kipei显然,明智的做法是正确格式化生成的JSON。编号的属性是不良设计的标志。 – CodeCaster

0

这里u为完整的例子

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; } 
     } 
    } 
+0

请解释你的方法。 – CodeCaster

相关问题