我有如下所示的JSON数据。我只包含一次列名来保存数据大小。请让我知道如何将其转换为C#对象列表。
// JSON
{
"COLUMNS": [
"id", "country","lastname", "firstname", "email", "category"
],
"DATA": [
[43, "USA", "jon", "doe", "doe@gmail.com", "HR"],
[44, "JAPAN", "tanaka", "yidi", "yidi@aol.com", "IT"]
]
}
// .NET
Employee emp = JsonConvert.DeserializeObject<Employee>(jsonData);
我应该能够访问像emp.lastname这样的对象属性。
此外,正如标题所示,我使用JsonConvert class中的Json.NET library。
答案 0 :(得分:1)
您将无法直接使用JsonConvert类,因为它希望所有属性都具有名称/映射,并且无法确定它,因为您实际上使用的是自定义格式。
您需要做的是创建一个包含列和数据的类,并将其序列化为,如下所示:
class CustomData
{
public string Columns { get; set; }
public object[,] Data { get; set; }
}
JsonConvert 应能够在.NET中将您的数据转换为此结构。
从那里开始,它变得更像是一个.NET问题,因为你必须得到列和数据的名称。您应该能够使用LINQ帮助配对两者,然后使用反射来填充您的项目:
// The custom data structure, deserialized from JSON.
CustomData data = ...;
// The type of Employee.
Type type = typeof(Employee);
// Create a map of the property info to the ordinal in the
// Columns.
IDictionary<int, PropertyInfo> propertyMap = data.Columns.
Select((p, i) =>
new { Index = i, PropertyInfo = type.GetProperty(p) }).
ToDictionary(p => p.Index, p => p.PropertyInfo);
// Cycle through the rows in the data.
var query =
// Cycle through all of the rows.
from row in Enumerable.Range(0, data.Data.GetLength(0))
// Create the instance.
let instance = new Employee()
// For each column in the row.
from column in Enumerable.Range(0, data.Data.GetLength(1))
// Lookup the property info.
let propertyInfo = propertyMap[column]
// Select the instance, the property, and the value.
select {
// This is used for grouping purposes, since
// you can't guarantee that the type you are serializing
// to will have natural identity properties and
// you know the row corresponds to one singular instance.
Row = row,
Instance = instance,
PropertyInfo = propertyInfo,
Value = data.Data[row, column]
};
// Iterate through the items, setting the instance values.
foreach (var propertyAndData in query)
{
// Set the property value on the instance.
propertyAndData.PropertyInfo.
SetValue(propertyAndData.Instance, Value, null);
}
// Group by the row and get the first item in each sequence.
IEnumerable<Employee> employees =
from item in query
groupby item by item.Row into g
select g.First();
上述唯一的警告;如果您使用的是值类型,则在遍历此操作时,不将填充相同的实例。为了处理值类型,您必须展开LINQ查询并使用for循环遍历每个行和列,在每个新行上创建新实例,然后使用上面的Reflection来填充属性。