I need to convert JSON data that I get from a REST API and convert them to CSV for some analytic. The problem is that the JSON data do not necessarily follow the same content, so I can't define a type for mapping. This has become a challenge that is taking too much of my time. I have already created some code, but of course it is not working as it throws exception on this line
var data = JsonConvert.DeserializeObject<List<object>>(jsonData);
The error is:
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[System.Object]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'data', line 2, position 10.
please let me know what I can do to get this going.
A sample of data would be like this, the fields of data can change very often, for example a new field can be added the next day, so I don't have the liberty to create a .Net class to map the data.
{
"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;
}
}
}
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
Json structure is made up with {}, [], comma, colon and double quotation marks and it includes the following data types: Object, Number, Boolean, String, and Array. Serialize means convert an object instance to an XML document. Deserialize means convert an XML document into an object instance.
Deserialization is transforming the data from a file or stream back into an object to be used in your application. This can be binary data or structured data like JSON and XML. Deserialization is the opposite of serialization, which transforms objects into byte streams or structured text.
A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.
The real issue here is that you are trying to deserialize into a List<object>
but your JSON actually represents a single object containing a data
property which then contains a list of objects. That is why you are getting this error. Json.Net can't deserialize a single object into a list. I think what you really want to do is define a container class like this:
class Root
{
public List<Dictionary<string, object>> Data { get; set;}
}
Then deserialize like this:
var data = JsonConvert.DeserializeObject<Root>(jsonData).Data;
You will then end up with a list of dictionaries, where each dictionary represents one item in the JSON array. The dictionary key-value pairs are the dynamic values in each item. You can then work with these as you would with any other dictionary. For example, here is how you would dump out all the data:
foreach (var dict in data)
{
foreach (var kvp in dict)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
Console.WriteLine();
}
Fiddle: https://dotnetfiddle.net/6UaKhJ
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With