从 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
成员——而你的成员都是私有的。
要解决这个问题,我可能建议完全跳过 DataTable
和 json_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;
您还可以将SelectRows
和Select
调用组合成一个方法;为了清楚起见,我将它们分开。跳过 DataTable
和 JSON 表示应该比您当前的方法更简单且性能更高。
使用模型数据阅读器here 演示小提琴。
【讨论】:
以上是关于从 JSON 填充多个对象的主要内容,如果未能解决你的问题,请参考以下文章
如何从 jquery 中的 json 格式对象填充 html 数据表
JQuery 自动完成:在一个字段中显示同一个 JSON 对象的多个属性
如何使用从 Spring MVC 发回的 JSON 对象填充 jQuery 数据表的行?