Подтвердить что ты не робот

Преобразование JSON в DataTable

У меня 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}
]

Как я могу преобразовать это в объект С# DataTable следующим образом?

---------------------------------------------------------------------
ID    |  Name     |  Add    |   Edit  | View   | Authorize
---------------------------------------------------------------------
10    | User      | true    |  true   | true   |  true
11    | Group     | true    |  true   | true   |  true
12    | Permission| true    |  true   | true   |  true
4b9b3361

Ответ 1

Отсоедините ваш jsonstring к некоторому классу

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

Напишите в свой проект следующий метод расширения

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

Метод расширения вызова, например

UserList.ToDataTable<User>();

Ответ 2

Существует более простой способ, чем другие ответы здесь, которые требуют сначала десериализации в класс С#, а затем превращения его в datatable.

Можно перейти непосредственно к datatable, с JSON.NET и следующим кодом:

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

Ответ 3

Он также может быть достигнут с помощью приведенного ниже кода.

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

Ответ 4

Каждый не всегда знает тип, в который десериализуется. Поэтому было бы удобно иметь любой JSON (содержащий некоторый массив) и динамически создавать таблицу из этого.

Однако может возникнуть проблема, когда десериализатор не знает, где искать массив для табуляции. Когда это произойдет, мы получим сообщение об ошибке, подобное следующему:

Неожиданный токен JSON при чтении DataTable. Ожидаемый StartArray, получил StartObject. Путь '', строка 1, позиция 1.

Даже если мы дадим ему поддержку или подготовим наш json соответственно, тогда типы "объектов" внутри массива все равно могут препятствовать табуляции, когда десериализатор не знает, как представлять объекты в терминах строк и т.д. В этом случае, возникают ошибки, подобные следующим:

Неожиданный токен JSON при чтении DataTable: StartObject. Path '[0].__ metadata', строка 3, позиция 19.

В приведенном ниже примере JSON включает обе эти проблемные функции:

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

Итак, как мы можем разрешить это и по-прежнему сохранять гибкость, не зная тип, в который следует отступить?

Ну вот простой подход, который я придумал (предполагая, что вы счастливы игнорировать свойства типа объекта, такие как __metadata в приведенном выше примере):

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

Я знаю, что это может быть больше "LINQy" и имеет абсолютно нулевую обработку исключений, но, надеюсь, концепция передается.

Мы начинаем использовать все больше и больше сервисов на моей работе, которые вертели JSON, поэтому освобождая себя от строгого ввода всего, это мое очевидное предпочтение, потому что я ленив!

Ответ 5

Здесь вы можете использовать JSON.Net. Взгляните на метод JsonConvert.DeserializeObject.

Ответ 6

Я рекомендую вам использовать JSON.NET. это библиотека с открытым исходным кодом для сериализации и десериализации ваших объектов С# в объекты json и Json в объекты .net...

Пример сериализации:

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

Ответ 7

Вот еще один простой подход для преобразования JSON в Datatable с использованием Cinchoo ETL - библиотеки с открытым исходным кодом

Пример ниже показывает, как конвертировать

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

Надеюсь, поможет.