我需要转换从REST API获取的JSON数据,并将它们转换为CSV以进行某些分析.问题是JSON数据不一定遵循相同的内容,因此我无法定义映射类型.这已经成为一项挑战,占用了我太多的时间.我已经创建了一些代码,但当然它没有工作,因为它在这一行引发了异常
var data = JsonConvert.DeserializeObject<List<object>>(jsonData);
Run Code Online (Sandbox Code Playgroud)
错误是:
附加信息:无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Collections.Generic.List`1 [System.Object]',因为该类型需要JSON数组(例如[1] ,2,3])正确反序列化.
要修复此错误,请将JSON更改为JSON数组(例如[1,2,3])或更改反序列化类型,使其成为普通的.NET类型(例如,不是像整数这样的基本类型,而不是类似的集合类型可以从JSON对象反序列化的数组或List.JsonObjectAttribute也可以添加到类型中以强制它从JSON对象反序列化.
路径'数据',第2行,第10位.
请让我知道我能做些什么才能实现这一目标.
数据样本将是这样的,数据字段可以经常更改,例如可以在第二天添加新字段,因此我没有自由创建.Net类来映射数据.
{
"data": [
{
"ID": "5367ab140026875f70677ab277501bfa",
"name": "Happiness Initiatives - Flow of Communication/Process & Efficiency",
"objCode": "PROJ",
"percentComplete": 100.0,
"plannedCompletionDate": "2014-08-22T17:00:00:000-0400",
"plannedStartDate": "2014-05-05T09:00:00:000-0400",
"priority": 1,
"projectedCompletionDate": "2014-12-05T08:10:21:555-0500",
"status": "CPL"
},
{
"ID": "555f452900c8b845238716dd033cf71b",
"name": "UX Personalization Think Tank and Product Strategy",
"objCode": "PROJ",
"percentComplete": 0.0,
"plannedCompletionDate": "2015-12-01T09:00:00:000-0500",
"plannedStartDate": "2015-05-22T09:00:00:000-0400",
"priority": 1,
"projectedCompletionDate": "2016-01-04T09:00:00:000-0500",
"status": "APR"
},
{
"ID": "528b92020051ab208aef09a4740b1fe9",
"name": "SCL Health System - full Sitecore implementation (Task groups with SOW totals in Planned hours - do not bill time here)",
"objCode": "PROJ",
"percentComplete": 100.0,
"plannedCompletionDate": "2016-04-08T17:00:00:000-0400",
"plannedStartDate": "2013-11-04T09:00:00:000-0500",
"priority": 1,
"projectedCompletionDate": "2013-12-12T22:30:00:000-0500",
"status": "CPL"
}
]
}
namespace BusinessLogic
{
public class JsonToCsv
{
public string ToCsv(string jsonData, string datasetName)
{
var data = JsonConvert.DeserializeObject<List<object>>(jsonData);
DataTable table = ToDataTable(data);
StringBuilder result = new StringBuilder();
for (int i = 0; i < table.Columns.Count; i++)
{
result.Append(table.Columns[i].ColumnName);
result.Append(i == table.Columns.Count - 1 ? "\n" : ",");
}
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < table.Columns.Count; i++)
{
result.Append(row[i].ToString());
result.Append(i == table.Columns.Count - 1 ? "\n" : ",");
}
}
return result.ToString().TrimEnd(new char[] {'\r', '\n'});
}
private DataTable ToDataTable<T>( IList<T> data )
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for (int i = 0 ; i < props.Count ; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0 ; i < values.Length ; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里真正的问题是您试图反序列化为一个,List<object>但您的 JSON 实际上表示一个包含一个data属性的对象,然后该对象包含一个对象列表。这就是您收到此错误的原因。Json.Net 无法将单个对象反序列化为列表。我认为你真正想做的是定义一个这样的容器类:
class Root
{
public List<Dictionary<string, object>> Data { get; set;}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样反序列化:
var data = JsonConvert.DeserializeObject<Root>(jsonData).Data;
Run Code Online (Sandbox Code Playgroud)
然后您将得到一个字典列表,其中每个字典代表 JSON 数组中的一个项目。字典键值对是每个项目中的动态值。然后,您可以像使用任何其他字典一样使用这些。例如,以下是转储所有数据的方法:
foreach (var dict in data)
{
foreach (var kvp in dict)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
Console.WriteLine();
}
Run Code Online (Sandbox Code Playgroud)
小提琴:https : //dotnetfiddle.net/6UaKhJ