c# - 从 JSON 填充多个对象

标签 c# mysql json datatable mysqldatareader

我有这个代码:

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"
   }
]

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

  • 客户(id=1),以及 User1(8,"manuel")User2(2,"michael") ;
  • 客户(id=2)User1(3,"friedrich")User2(6,"antony") .

最佳答案

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 成员 - 而您的都是私有(private)的。

要解决此问题,我可能建议完全跳过 DataTablejson_string 表示形式,并直接从 IDataReader 构建列表。接口(interface) MySqlDataReader实现:

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://stackoverflow.com/a/1202973
    // To https://stackoverflow.com/questions/1202935/convert-rows-from-a-data-reader-into-typed-results
    // By https://stackoverflow.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 表示形式应该比您当前的方法更简单、更高效。

使用模型数据读取器的演示 fiddle here .

关于c# - 从 JSON 填充多个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56173539/

相关文章:

c# - 添加和删​​除文件片段而不完全重写它的最有效方法是什么?

c# - 根据 ListView 项过滤字符串集合

php - mysql JOIN 让我打败了

javascript - Moves App API 调用在浏览器中有效,但在程序中失败(帖子中包含 URL)

json - 使用带有 AngularJS 的复选框过滤数组

c# - 确定使用 Azure 移动应用服务拉取了多少更改?

c# - 加入 LINQ 和 Entity Framework

c# - 如何使用 AddOrUpdate 的多个条件来确定数据库是否应该添加模型或更新?

mysql - 使用 Grep 在每行循环中创建多个变量 - BASH

javascript - ajax,变量未定义?