Convertir JSON a tabla de datos

Resuelto Nithesh Narayanan asked hace 12 años • 9 respuestas

Tengo JSON en el siguiente 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}
]

¿ Cómo puedo convertir eso en un DataTableobjeto C# de la siguiente manera?

---------------------------------------------------------------------
ID    |  Name     |  Add    |   Edit  | View   | Authorize
---------------------------------------------------------------------
10    | User      | true    |  true   | true   |  true
11    | Group     | true    |  true   | true   |  true
12    | Permission| true    |  true   | true   |  true
Nithesh Narayanan avatar Aug 16 '12 12:08 Nithesh Narayanan
Aceptado

Existe un método más sencillo que las otras respuestas aquí, que requieren primero deserializar en la clase ac# y luego convertirla en una tabla de datos.

Es posible ir directamente a una tabla de datos, con JSON.NET y código como este:

DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Kyle avatar Dec 03 '2014 22:12 Kyle

Deserializa tu jsonstring a alguna clase

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

Escriba el siguiente método de extensión para su proyecto

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

Método de extensión de llamada como

UserList.ToDataTable<User>();
Pravin Pawar avatar Aug 16 '2012 07:08 Pravin Pawar

No siempre se sabe en qué tipo deserializar. Por lo tanto, sería útil poder tomar cualquier JSON (que contenga alguna matriz) y generar dinámicamente una tabla a partir de él.

Sin embargo, puede surgir un problema en el que el deserializador no sabe dónde buscar la matriz para tabular. Cuando esto sucede, recibimos un mensaje de error similar al siguiente:

Token JSON inesperado al leer DataTable. StartArray esperado, obtuve StartObject. Ruta '', línea 1, posición 1.

Incluso si lo animamos o preparamos nuestro json en consecuencia, los tipos de "objetos" dentro de la matriz aún pueden evitar que se produzca la tabulación, donde el deserializador no sabe cómo representar los objetos en términos de filas, etc. , se producen errores similares a los siguientes:

Token JSON inesperado al leer DataTable: StartObject. Ruta '[0].__metadata', línea 3, posición 19.

El siguiente ejemplo JSON incluye estas dos características problemáticas:

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

Entonces, ¿cómo podemos resolver esto y seguir manteniendo la flexibilidad de no saber en qué tipo desrializar?

Bueno, aquí hay un enfoque simple que se me ocurrió (suponiendo que esté dispuesto a ignorar las propiedades del tipo de objeto, como __metadata en el ejemplo anterior):

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

Sé que esto podría ser más "LINQy" y no tiene absolutamente ningún manejo de excepciones, pero espero que se transmita el concepto.

Estamos empezando a utilizar cada vez más servicios en mi trabajo que escupen JSON, por lo que liberarnos de escribir todo con fuerza es mi preferencia obvia porque soy vago.

ne1410s avatar Jan 21 '2016 11:01 ne1410s