如何将带有子属性的 JSON 反序列化为 C# 中的 ONE 对象

Posted

技术标签:

【中文标题】如何将带有子属性的 JSON 反序列化为 C# 中的 ONE 对象【英文标题】:How to deserialize JSON with child attribute into ONE object in C# 【发布时间】:2019-10-06 00:10:08 【问题描述】:

我的 JSON 对象由一致的属性 udiddateevent_idparameters 内部的不同但已知的属性组成。下面有两个对象:

      
        "udid": "70baf33f-f011-44ee-b35a-6064b5ab468d",
        "date": "2018-01-01",
        "event_id": 2,
        "parameters": 
          "gender": "male",
          "age": 13,
          "country": "India"
        
      ,
      
        "udid": "70baf33f-f011-44ee-b35a-6064b5ab468d",
        "date": "2018-01-01",
        "event_id": 1,
        "parameters": 
      

这样的 JSON 可以在一个对象中表示,如果我像这样在顶层移动参数:

public class Event

    [Key]
    public int Id  get; set; 
    public string udid  get; set; 
    public DateTime date  get; set; 
    public int event_id  get; set;
    public string gender  get; set; 
    public int age  get; set; 
    public string country  get; set; 
    public int stage  get; set; 
    public bool win  get; set; 
    public int time  get; set; 
    public int income  get; set; 
    public string name  get; set; 
    public double price  get; set; 
    public string item  get; set; 

那么,由于我有 3000 万条这样的记录,我该如何有效地反序列化它?我正在使用 newtonsoft.json。


编辑:

按照 Liam 的建议,我最终创建了三个对象(嵌套在 EventNested 内的 Parameters)和扁平化的 Event。我随便将 json 反序列化为 EventNested,然后使用这个庞大的 LINQ 表达式将其重新映射为 Event:

List<EventNested> eventsNested = JsonConvert.DeserializeObject<List<EventNested>>(json);
List<Event> events = eventsNested.Select(x=> new Event 
        date = x.date,
        udid = x.udid,
        event_id = x.event_id,
        parametersAge = x.Parameters.age,
        parametersCountry = x.Parameters.country, 
        parametersGender = x.Parameters.gender, 
        parametersIncome = x.Parameters.income,
        parametersItem = x.Parameters.item, 
        parametersName = x.Parameters.name,
        parametersPrice = x.Parameters.price, 
        parametersStage = x.Parameters.stage,
        parametersTime = x.Parameters.time, 
        parametersWin = x.Parameters.win
     ).ToList();

【问题讨论】:

Generically Flatten Json using c#的可能重复 【参考方案1】:

只需将一个对象嵌套在另一个对象中。 (如果您使用的是 EF,最好有 2 个单独的事件:一个用于您的 DbSet(没有嵌套对象),另一个作为 JSON 数据协定。)

public class Event

    //.. the rest of your attributes here
    public EventParameters Parameters  get; set; 



public class EventParameters

    public int? Age  get; set;  // If such parameter may not exist in your JSON, ensure it to be nullable in your POCO.
    public string Country  get; set; 
    public string Gender  get; set; 

【讨论】:

问题是,如果我想从事件中访问 EventParameters,我必须将它包含在 Events.include(x=&gt;x.EventParameters).ToList() 中,这将需要大约 20 倍的 RAM。另外我正在使用 BulkInsert,它在没有嵌套对象的情况下效果最好。也许我做错了什么,所以纠正我 如果你不想在你的 DbContext 中有一个单独的参数表,我会这样做: 1. 创建三个类:为你的事件创建一个平面 DbSet 和一个带有 JsonEventParameters 的 JsonEvent它。 2. 在保存之前将一个映射到另一个(通过 AutoMapper 或手动) 啊,谢谢。我只是第一次尝试弄乱自动映射器,认为它会更快。但我放弃并坚持使用 LINQ 映射,结果发现它运行得很快。因此,您的 3 个对象的解决方案效果最佳

以上是关于如何将带有子属性的 JSON 反序列化为 C# 中的 ONE 对象的主要内容,如果未能解决你的问题,请参考以下文章

C#反序列化带有ID节点的Json [重复]

将 JSON 命名属性反序列化为 .Net 对象

在将 JSON 反序列化为 C# 对象之前检查属性值

将 JSON 数组反序列化为 List<T> C# 时出错

将 JSON 反序列化为 C# 对象以在网格中将嵌套数组显示为字符串

如何将具有嵌套属性的 JSON 对象反序列化为 Symfony 实体?