Converter JSON para DataTable

Tenho o JSON no seguinte formato:

[
    {"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}
]
Como posso converter isso num objecto c# DataTable como se segue?

---------------------------------------------------------------------
ID    |  Name     |  Add    |   Edit  | View   | Authorize
---------------------------------------------------------------------
10    | User      | true    |  true   | true   |  true
11    | Group     | true    |  true   | true   |  true
12    | Permission| true    |  true   | true   |  true
Author: Ry-, 2012-08-16

7 answers

Deserializa o teu jsonstring para alguma classe.
List<User> UserList = JsonConvert.DeserializeObject<List<User>>(jsonString);

Escrever de acordo com o método de extensão para o seu projecto

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

Método de extensão de chamadas como

UserList.ToDataTable<User>();
 37
Author: Pravin Pawar, 2018-07-05 10:44:06
Há um método mais fácil do que as outras respostas aqui, que requerem primeiro a deserialização para uma classe C#, e depois transformá-la em um datatable. É possível ir diretamente a um datável, com JSON.NET e código como este:
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
 44
Author: Kyle, 2014-12-03 22:05:28

Também pode ser alcançado usando o código abaixo.

DataSet data = JsonConvert.DeserializeObject<DataSet>(json);
 16
Author: Mohammed Ghouse, 2015-02-06 16:33:01
Nem sempre se sabe o tipo para deserializar. Então seria útil ser capaz de tomar qualquer JSON (que contém algum array) e dinamicamente produzir uma tabela a partir disso.

Um problema pode surgir no entanto, onde o desertor não sabe onde procurar a matriz para tabular. Quando isso acontece, recebemos uma mensagem de erro semelhante ao seguinte:

Símbolo JSON inesperado quando se lê datável. Esperado StartArray, tenho lançamento estelar. Path", linha 1, posição 1.

Mesmo que lhe demos encorajamento ou preparemos o nosso json de acordo, então os tipos de "objecto" dentro da matriz ainda podem impedir que a tabulação ocorra, onde o desertor não sabe como representar os objectos em termos de linhas, etc. Neste caso, ocorrem erros semelhantes aos seguintes:

Token JSON inesperado ao ler datable: start Tojet. Path "[0].__metadata", linha 3, posição 19.

O exemplo abaixo JSON inclui: ambas as características problemáticas:

{
  "results":
  [
    {
      "Enabled": true,
      "Id": 106,
      "Name": "item 1",
    },
    {
      "Enabled": false,
      "Id": 107,
      "Name": "item 2",
      "__metadata": { "Id": 4013 }
    }
  ]
}
Então, como podemos resolver isso, e ainda manter a flexibilidade de não saber o tipo para ridicularizar?

Bem, aqui está uma abordagem simples que eu inventei (assumindo que você está feliz em ignorar as propriedades do tipo de objeto, tais como _ _ metadados no exemplo acima):

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());
}
Eu sei que isto pode ser mais "LINQy" e não tem nenhum tratamento de excepção, mas espero que o conceito seja transmitido. Estamos a começar a usar mais e mais serviços no meu trabalho que devolvem o JSON, por isso, libertar-nos de digitar tudo fortemente, é a minha preferência óbvia porque sou preguiçoso!
 2
Author: ne1410s, 2018-07-05 10:44:57
 1
Author: danish, 2012-08-16 06:02:46

Recomendo que use JSON.NET . é uma biblioteca de código aberto para serializar e deserializar os seus objectos c# nos objectos json e Json nos objectos .net...

Exemplo De Serialização:

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);
 1
Author: Talha, 2012-08-16 06:50:26

Aqui está outra abordagem sem descontinuidades para converter JSON para datável usando Cinchoo ETL - uma biblioteca de código aberto

A amostra abaixo mostra como converter

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();
}
Espero que ajude.
 0
Author: RajN, 2018-07-31 15:47:04