简体   繁体   中英

JSON object to Datatable in C#

I've the following c# Class

public class Output
        {
            public string name { get; set; }
            public string[] results { get; set; }
        }

Which results in below output after execution

[
  {
    "name": "Field1",
    "results": [
      "One",
      "Two",
      "Three"
    ]
  },
  {
    "name": "Field2",
    "results": [
      "One",
      "Two",
      "Three",
      "Four"
    ]
  }
]

Is there any utility or library which can convert my JSON into DataTable. I checked the JSON.net example but that require the JSON must be in below format to convert that into table

string json = @"[{"Field1" : "One", "Field2": "One"}
{"Field1" : "Two", "Field2": "Two"}
{"Field1" : "Three", "Field2": "Three"}
{"Field1" : "", "Field2": "Four"}];

var table = JsonConvert.DeserializeObject<DataTable>(json);

Also, Any clue if my JSON can be converted in the format needs for JsonConvert.DeserializeObject

It's not duplicate, the question marked in duplicate discusses the best way instead the complex JSON format example i provided here.

Expected Output

Field1,  Field2
One, One
Two, Two
Three, Three
null,Four

JsonConver.DeserializeObject does not provide you with an easy way to achieve your goal. It would be much easier to write a simple parser from a list of Output s to a DataTable . I provide you with code:

public static class Helper
{
    public static DataTable ToDataTable(this List<Program.Output> list)
    {
        var dt = new DataTable();

        // insert enough amount of rows
        var numRows = list.Select(x => x.results.Length).Max();
        for (int i = 0; i < numRows; i++)
            dt.Rows.Add(dt.NewRow());

        // process the data
        foreach (var field in list)
        {
            dt.Columns.Add(field.name);
            for (int i = 0; i < numRows; i++)
                // replacing missing values with empty strings
                dt.Rows[i][field.name] = i < field.results.Length ? field.results[i] : string.Empty; 
        }

        return dt;
    }
}

And the example of usage:

public class Program
{
    static void Main(string[] args)
    {
        var s = "[{\"name\": \"Field1\", \"results\": [\"One\", \"Two\", \"Three\"]}, {\"name\": \"Field2\", \"results\": [\"One\", \"Two\", \"Three\", \"Four\"]}]";
        var o = JsonConvert.DeserializeObject<List<Output>>(s);
        // convert the list to a DataTable
        var dt = o.ToDataTable();
    }

    public class Output
    {
        public string name { get; set; }
        public string[] results { get; set; }
    }
}

What you could do is to convert the JSON data back to a List of Object like

JsonConvert.DeserializeObject<List<CustomerJson>>(json);

and then convert it to a DataTable with a converter method

public static DataTable ToDataTable<T>(this 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;        
}

I suggest to convert your JSON back to array of Output objects. You can use JsonDataContractSerializer (requires annotations) or JavascriptSerializer (requires referencing System.Web.Extensions) for that purpose.

Having an array of Output objects you can do the following:

DataTable ConstructDataTable(Output[] outputArray)
{
  var table = new DataTable();
  var columnNames = outputArray.Select(i => i.name).Distinct().ToArray();
  var rows = outputArray.SelectMany(i => i.result).Distinct().ToArray();
  foreach(var cn in columnNames)
     table.Columns.Add(cn, typeof(string));
  foreach(var r in rows)
  {
    object[] values = new object[columnNames.Length];
    for (int i = 0; i < columnNames.Length; i++)
    {
      values[i] = outputArray.First(i => i.name == columnNames[i]).results.FirstOrDefault(i => i == r);
    }
    table.Rows.Add(values);
  }
  return table;
}

used Referances :

  using Newtonsoft.Json;
  using System.Collections.Generic;
  using System.Data;
  using System.IO;
  using FastMember;

Your Class:

  public class Output
  {
        public string name { get; set; }
        public string[] results { get; set; }
  }

And :

        var s = "[{\"name\": \"Field1\", \"results\": [\"One\", \"Two\", \"Three\"]}, {\"name\": \"Field2\", \"results\": [\"One\", \"Two\", \"Three\", \"Four\"]}]";
        List<Output> data = JsonConvert.DeserializeObject<List<Output>>(s);

        DataTable dt = new DataTable(); 
        using (var reader = ObjectReader.Create(data))
        {
            dt.Load(reader);
        }
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM