从 JSON 填充多个对象

Posted

技术标签:

【中文标题】从 JSON 填充多个对象【英文标题】:Populate multiple objects from JSON 【发布时间】:2019-10-04 00:37:37 【问题描述】:

我有这个代码:

public class Customer

    Int32 id  get; set;  = 0;
    User user1  get; set;  = null;
    User user2  get; set;  = null;


/* ... */

using (mysqlConnection conn = new MySqlConnection(Costanti.connessione))

    conn.Open();
    MySqlCommand m = new MySqlCommand("
SELECT c1.*, u1.*, u2.*
FROM customers as c1
inner join utenti u1 on u1.customer_id = c1.id
inner join utenti u2 on u2.customer_id = c1.id
", conn);

    MySqlDataReader x = m.ExecuteReader();
    DataTable dataTable = new DataTable();
    dataTable.Load(x);
    String json_string = Newtonsoft.Json.JsonConvert.SerializeObject(dataTable);

    List<Customer> lista = new List<Customer>();
    Newtonsoft.Json.JsonConvert.PopulateObject(json_string, lista);
    conn.Close();

如何将 select 的 c1.* 字段映射到通用 Customer customer_1,然后将 u1.*u2.* 映射到 customer_1 的属性? Newtonsoft.Json.JsonConvert.PopulateObject 不允许我这样做。

中间的json_string 看起来像:

[
   
      "id":1,
      "id_user":8,
      "name":"manuel",
      "id_user1":2,
      "name1":"michael"
   ,
   
      "id":2,
      "id_user":3,
      "name":"friedrich",
      "id_user1":6,
      "name1":"antony"
   
]

结果必须是由以下组成的列表:

Customer(with id=1),与User1(8,"manuel")User2(2,"michael")Customer(with id=2),与User1(3,"friedrich")User2(6,"antony")

【问题讨论】:

json_string 是什么样的? 看起来像这样: [ "id":1, "id_user":8, "name":"manuel", "id_user1":2, "name1":"michael", , "id":2, "id_user":3, "name":"friedrich", "id_user1":6, "name1":"antony", , ] 结果必须是由以下组成的列表:客户(id=1),用户1(8,“manuel”)和用户2(2,“迈克尔”);客户(id=2),用户1(3,“friedrich”)和用户2(6,“安东尼”); 【参考方案1】:

您对PopulateObject() 的调用不起作用的主要原因是您的 c# 数据模型与 JSON 的架构不匹配。如果我使用 How to auto-generate a C# class file from a JSON object string 中的工具之一从您的 JSON 自动生成数据模型,我会得到:

public class RootObject

    public int id  get; set; 
    public int id_user  get; set; 
    public string name  get; set; 
    public int id_user1  get; set; 
    public string name1  get; set; 

这看起来不像你的 Customer 类。

PopulateObject() 失败的第二个原因是 Json.NET 默认只会填充 public 成员——而你的成员都是私有的。

要解决这个问题,我可能建议完全跳过 DataTablejson_string 表示,并直接从 MySqlDataReader 实现的 IDataReader 接口构建您的列表:

var lista = x
    .SelectRows(r =>
        // Extract the row data by name into a flat object
        new
        
            id = Convert.ToInt32(r["id"], NumberFormatInfo.InvariantInfo),
            id_user = Convert.ToInt32(r["id_user"], NumberFormatInfo.InvariantInfo),
            name = r["name"].ToString(),
            id_user1 = Convert.ToInt32(r["id_user1"], NumberFormatInfo.InvariantInfo),
            name1 = r["name1"].ToString(),
        )
    .Select(r =>
        // Convert the flat object to a `Customer`.
        new Customer
        
            id = r.id,
            user1 = new User  Id = r.id_user, Name = r.name ,
            user2 = new User  Id = r.id_user1, Name = r.name1 ,
        )
        .ToList();

使用扩展方法:

public static class DataReaderExtensions

    // Adapted from this answer https://***.com/a/1202973
    // To https://***.com/questions/1202935/convert-rows-from-a-data-reader-into-typed-results
    // By https://***.com/users/3043/joel-coehoorn
    public static IEnumerable<T> SelectRows<T>(this IDataReader reader, Func<IDataRecord, T> select)
    
        while (reader.Read())
        
            yield return select(reader);
        
    

这假设您的 Customer 数据模型现在看起来像:

public class Customer

    public Int32 id  get; set; 
    public User user1  get; set; 
    public User user2  get; set; 


public class User

    public Int32 Id  get; set; 
    public string Name  get; set; 

您还可以将SelectRowsSelect 调用组合成一个方法;为了清楚起见,我将它们分开。跳过 DataTable 和 JSON 表示应该比您当前的方法更简单且性能更高。

使用模型数据阅读器here 演示小提琴。

【讨论】:

以上是关于从 JSON 填充多个对象的主要内容,如果未能解决你的问题,请参考以下文章

如何从 jquery 中的 json 格式对象填充 html 数据表

JQuery 自动完成:在一个字段中显示同一个 JSON 对象的多个属性

如何使用从 Spring MVC 发回的 JSON 对象填充 jQuery 数据表的行?

JavaScript - 从多个数组填充对象构造函数

如何使用嵌套的 json 对象填充 vue 条件库中的 vue 组件

.Net Core 3.0 JsonSerializer 填充现有对象