web-dev-qa-db-fra.com

Convertir JSON en DataTable

J'ai JSON dans le format suivant:

[
    {"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}
]

Comment puis-je convertir cela en un objet C # DataTable comme suit?

---------------------------------------------------------------------
ID    |  Name     |  Add    |   Edit  | View   | Authorize
---------------------------------------------------------------------
10    | User      | true    |  true   | true   |  true
11    | Group     | true    |  true   | true   |  true
12    | Permission| true    |  true   | true   |  true
37
Nithesh

Désérialisez votre jsonstring en classe

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

Écrivez suivant méthode d'extension à votre projet

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éthode d'extension d'appel comme

UserList.ToDataTable<User>();
40
Pravin Pawar

Il existe une méthode plus simple que les autres réponses ici, qui nécessitent d’abord une désérialisation en une classe c #, puis en la transformant en une datatable. 

Il est possible d’aller directement à un serveur de données, avec JSON.NET et un code comme celui-ci:

DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
50
Kyle

Il peut également être réalisé en utilisant le code ci-dessous.

DataSet data = JsonConvert.DeserializeObject<DataSet>(json);
18
Mohammed Ghouse

On ne sait pas toujours le type dans lequel désérialiser. Il serait donc pratique de pouvoir utiliser n'importe quel JSON (contenant un tableau) et de générer dynamiquement une table à partir de cela.

Un problème peut toutefois survenir, où le désérialiseur ne sait pas où chercher le tableau à tabuler. Lorsque cela se produit, nous obtenons un message d'erreur semblable à celui-ci:

Jeton JSON inattendu lors de la lecture de DataTable. Attendu StartArray, a obtenu StartObject. Chemin '', ligne 1, position 1.

Même si nous l'encourageons ou préparons notre json en conséquence, les types "objet" du tableau peuvent toujours empêcher la tabulation, lorsque le désérialiseur ne sait pas comment représenter les objets en termes de lignes, etc. , des erreurs similaires aux suivantes se produisent:

Jeton JSON inattendu lors de la lecture de DataTable: StartObject. Chemin '[0] .__ métadonnées', ligne 3, position 19.

L'exemple JSON ci-dessous inclut ces deux fonctionnalités problématiques:

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

Alors, comment pouvons-nous résoudre ce problème, tout en conservant la flexibilité de ne pas savoir le type dans lequel dérioriser?

Eh bien, voici une approche simple que j'ai proposée (en supposant que vous souhaitiez ignorer les propriétés de type d'objet, telles que __metadata dans l'exemple ci-dessus):

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

Je sais que cela pourrait être plus "LINQy" et ne gère absolument aucune exception, mais j'espère que le concept est transmis.

Nous commençons à utiliser de plus en plus de services dans mon travail qui génèrent du JSON, libérant ainsi tout ce qui est dactylographié, voilà ma préférence évidente car je suis paresseux!

2
ne1410s

Vous pouvez utiliser JSON.Net ici. Jetez un coup d'œil à la méthode JsonConvert.DeserializeObject.

1
danish

Je vous recommande d'utiliser JSON.NET . c'est une bibliothèque open source pour sérialiser et désérialiser vos objets c # en objets json et Json en objets .net ...

Exemple de sérialisation:

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
Talha

Voici une autre approche transparente pour convertir JSON en Datatable en utilisant Cinchoo ETL - une bibliothèque open source

Exemple ci-dessous montre comment convertir 

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

J'espère que ça aide.

0
RajN