75

I have JSON in the following format:

[
    {"id":"10","name":"User","add":false,"edit":true,"authorize":true,"view":true},
    {"id":"11","name":"Group","add":true,"edit":false,"authorize":false,"view":true},
    {"id":"12","name":"Permission","add":true,"edit":true,"authorize":true,"view":true}
]

How can I convert that into a C# DataTable object as follows?

---------------------------------------------------------------------
ID    |  Name     |  Add    |   Edit  | View   | Authorize
---------------------------------------------------------------------
10    | User      | true    |  true   | true   |  true
11    | Group     | true    |  true   | true   |  true
12    | Permission| true    |  true   | true   |  true
Ry-
  • 218,210
  • 55
  • 464
  • 476
Nithesh Narayanan
  • 11,481
  • 34
  • 98
  • 138
  • 1
    Please look at the answer to [this][1] question as a reference. [1]: http://stackoverflow.com/questions/2246694/how-to-convert-json-object-to-custom-c-sharp-object – bala_88 Aug 16 '12 at 06:04
  • 2
    possible duplicate of [How to convert json into datatable?](http://stackoverflow.com/questions/7641004/how-to-convert-json-into-datatable) – Eino N. Jul 23 '15 at 09:18

9 Answers9

104

There is an easier method than the other answers here, which require first deserializing into a c# class, and then turning it into a datatable.

It is possible to go directly to a datatable, with JSON.NET and code like this:

DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Kyle
  • 32,731
  • 39
  • 134
  • 184
61

Deserialize your jsonstring to some class

List<User> UserList = JsonConvert.DeserializeObject<List<User>>(jsonString);

Write following extension method to your project

using System.ComponentModel;

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;        
}

Call extension method like

UserList.ToDataTable<User>();
TECNO
  • 162
  • 2
  • 3
  • 15
Pravin Pawar
  • 2,559
  • 3
  • 34
  • 40
  • 2
    What is JsonConvert? Shall i need to include any namespace? it getting error – Nithesh Narayanan Aug 16 '12 at 07:16
  • I'm trying to use the above extension method - No Errors on build. But I do get a compilation error : "Compiler Error Message: CS0121: The call is ambiguous between the following methods or properties: 'ExtensionHelpers.ToDataTable<_Default.Jobs>(System.Collections.Generic.IList<_Default.Jobs>)' and 'ExtensionHelpers.ToDataTable<_Default.Jobs>(System.Collections.Generic.IList<_Default.Jobs>)'" Do you have any idea what might be causing it? @PravinPawar – Lord-David Jun 18 '15 at 07:20
  • Will have to look at the code. Are you calling this method on IList object? – Pravin Pawar Jun 19 '15 at 07:23
  • 1
    JsonConvert is part of the JSON.Net library by [NewtonSoft](http://www.newtonsoft.com/json). – Nikhil Girraj Jan 04 '17 at 07:37
  • Take a look at this answer http://stackoverflow.com/a/27282579/1308743 it doesn't require serializing to a class first. – Kyle Apr 25 '17 at 16:35
  • @PravinPawr kindly update TpeDescriptor to TypeDescriptor. spelling mistake. – Razim Khan Jul 14 '21 at 12:15
27

One doesn't always know the type into which to deserialize. So it would be handy to be able to take any JSON (that contains some array) and dynamically produce a table from that.

An issue can arise however, where the deserializer doesn't know where to look for the array to tabulate. When this happens, we get an error message similar to the following:

Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1.

Even if we give it come encouragement or prepare our json accordingly, then "object" types within the array can still prevent tabulation from occurring, where the deserializer doesn't know how to represent the objects in terms of rows, etc. In this case, errors similar to the following occur:

Unexpected JSON token when reading DataTable: StartObject. Path '[0].__metadata', line 3, position 19.

The below example JSON includes both of these problematic features:

{
  "results":
  [
    {
      "Enabled": true,
      "Id": 106,
      "Name": "item 1",
    },
    {
      "Enabled": false,
      "Id": 107,
      "Name": "item 2",
      "__metadata": { "Id": 4013 }
    }
  ]
}

So how can we resolve this, and still maintain the flexibility of not knowing the type into which to derialize?

Well here is a simple approach I came up with (assuming you are happy to ignore the object-type properties, such as __metadata in the above example):

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Linq;
...

public static DataTable Tabulate(string json)
{
    var jsonLinq = JObject.Parse(json);

    // Find the first array using Linq
    var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
    var trgArray = new JArray();
    foreach (JObject row in srcArray.Children<JObject>())
    {
        var cleanRow = new JObject();
        foreach (JProperty column in row.Properties())
        {
            // Only include JValue types
            if (column.Value is JValue)
            {
                cleanRow.Add(column.Name, column.Value);
            }
        }

        trgArray.Add(cleanRow);
    }

    return JsonConvert.DeserializeObject<DataTable>(trgArray.ToString());
}

I know this could be more "LINQy" and has absolutely zero exception handling, but hopefully the concept is conveyed.

We're starting to use more and more services at my work that spit back JSON, so freeing ourselves of strongly-typing everything, is my obvious preference because I'm lazy!

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
ne1410s
  • 6,864
  • 6
  • 55
  • 61
25

It can also be achieved using below code.

DataSet data = JsonConvert.DeserializeObject<DataSet>(json);
EvergreenTree
  • 1,788
  • 2
  • 16
  • 30
Mohammed Ghouse
  • 251
  • 3
  • 2
3

You can make use of JSON.Net here. Take a look at JsonConvert.DeserializeObject method.

danish
  • 5,550
  • 2
  • 25
  • 28
3

Here is another seamless approach to convert JSON to Datatable using Cinchoo ETL - an open source library

Sample below shows how to convert

string json = @"[
{""id"":""10"",""name"":""User"",""add"":false,""edit"":true,""authorize"":true,""view"":true},
{ ""id"":""11"",""name"":""Group"",""add"":true,""edit"":false,""authorize"":false,""view"":true},
{ ""id"":""12"",""name"":""Permission"",""add"":true,""edit"":true,""authorize"":true,""view"":true}
]";

using (var r = ChoJSONReader.LoadText(json))
{
    var dt = r.AsDataTable();
}

Sample fiddle: https://dotnetfiddle.net/y0siCi

Cinchoo
  • 6,088
  • 2
  • 19
  • 34
  • This looks great, but I had issues with it. It created the DataColumns correctly, but put all the rows values in a single row with System.Object[] in each column. – BClaydon Apr 21 '20 at 19:19
  • I need sample code, can you please raise issue here or github? – Cinchoo Apr 21 '20 at 22:01
2

I recommend you to use JSON.NET. it is an open source library to serialize and deserialize your c# objects into json and Json objects into .net objects ...

Serialization Example:

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": new Date(1230422400000),
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
Talha
  • 18,898
  • 8
  • 49
  • 66
2
json = File.ReadAllText(System.AppDomain.CurrentDomain.BaseDirectory + "App_Data\\" +download_file[0]);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Palle Due
  • 5,929
  • 4
  • 17
  • 32
0

I solved it by the following - Used Pravin Pawar's answer below - for converting the JSON object to dt.

https://stackoverflow.com/a/11982180/504351

1)Send the JSON from Angular to C# controller method. 2)In C# Controller method -

convert the string data (JSON object) to a datatable.

DataTable dt = (DataTable)JsonConvert.DeserializeObject(data, (typeof(DataTable)));

3)Create a table in SQL Server database by parsing through rows and columns of the datatable dt


int dt_length = dt.Columns.Count;
            Random rand = new Random();
            string tablename = "Test" + rand.Next().ToString();
            string query = "Create table " + tablename + "  ( ";
            
            for (int i = 0; i < dt_length; i ++)
            {
                if(i == dt_length -1)
                {
                    query = query + dt.Columns[i].ColumnName + " varchar(max) ) ";
                    
                }
                else
                {
                    query = query + dt.Columns[i].ColumnName + " varchar(max), ";
                }
            }               

4)Similarly insert each of the row data in the table created. 5)This helps to dynamically create a database table from JSON.