Uno no siempre sabe el tipo en el que deserializar. Por lo tanto, sería útil poder tomar cualquier JSON (que contenga alguna matriz) y producir dinámicamente una tabla a partir de eso.
Sin embargo, puede surgir un problema cuando el deserializador no sabe dónde buscar la matriz para tabular. Cuando esto sucede, obtenemos un mensaje de error similar al siguiente:
Token JSON inesperado al leer DataTable. Se esperaba StartArray, obtuvo StartObject. Path '', línea 1, posición 1.
Incluso si damos viene estímulo o preparar nuestra JSON en consecuencia, a continuación, los tipos de "objeto" dentro de la matriz todavía se puede evitar que se produzca la tabulación, donde el deserializer no lo hace saber cómo representar los objetos en términos de filas, etc. En este caso, 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 aún así mantener la flexibilidad de no saber el tipo de derialización?
Bueno aquí es un método simple que se me ocurrió (suponiendo que están dispuestos a pasar por alto las propiedades de 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 Linq y tiene absolutamente 0 manejo de excepciones, pero ojalá se transmita el concepto. Estamos comenzando a utilizar más y más servicios en mi trabajo que escupió JSON, por lo que nos liberamos de todo lo que escribimos fuertemente, es mi obvia preferencia porque soy flojo.
Mire la respuesta a esta pregunta [1] como referencia. [1]: http://stackoverflow.com/questions/2246694/how-to-convert-json-object-to-custom-c-sharp-object –
posible duplicado de [Cómo convertir JSON en tabla de datos?] (http://stackoverflow.com/questions/7641004/how-to-convert-json-into-datatable) – wildcat