Marc Rubiño

ASP.NET, C#, AJAX.NET, JavaScript, etc.

December 2011 - Artículos

Deserializar JSon a tipo anónimo .Net

En ciertas ocasiones podemos necesitar deserializar un objeto pasado desde un cliente en formato JSon a un tipo .net anónimo. Por ejemplo si utilizas MongoDB con el driver NORM y pretendes filtrar u ordenar de una manera dinámica, es difícil pasar estos objetos a la query para poder generar un filtro dinámico.

Para hacernos una idea esta sería una consulta paginada y con un filtro sencillo con NORM:

1 //NoRM anonymous objects:
2 return GetRepository().GetCollection("Personas")
3 .Find(
4 new { Nombre = Q.IsNotNull() }, //Where
5 new { Fecha = OrderBy.Descending }, //OrderBy
6 10, // Nº elementos de la secuencia "Skip"
7 0 // Primer elemento de la secuencia "Take"
8 );

 

Esta consulta nos devolvería las 10 primeras personas con Nombre que no sea null.

Tanto al utilizar los tipos anónimos como en las consultas LinQ se tiene que especificar la propiedad por la que se quiere filtrar u ordenar y eso nos limita a la hora de intentar hacer estas consultas de forma dinámica.

Parara hacer una prueba crearemos un tipo específico para utilizar en las consultas desde javaScript.

Lo ideal sería:

1 public class QueryRequest
2 {
3 public int Pagina { get; set; }
4 public int Registros { get; set; }
5 public object Orden { get; set; }
6 public object Filtro { get; set; }
7 }

 

Con este tipo nos pasarían como parámetros lel número de página, la cantidad de registros y además un object para filtrar y otro object para ordenar.

Pero esto no funciona porque NORM no lo reconoce como tipo anónimo y si lo intentamos pasar como string tampoco funciona.

Ahora solo nos queda intentar deserializar directamente nosotros el objeto JSON en un tipo anónimo y para eso utilizaremos el tipo dynamic que tenemos disponible desde c# 4.

Para eso solo tenemos que deserializar un texto con datos en formato JSon utilizandoJavaScriptSerializerque te permite utilizar un tipo T.

1 var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
2 var ObjetoAnonimo = jss.Deserialize(strJson);

 

Con estas dos líneas lo tenemos solucionado y el nuevo tipo podría quedar de esta manera para facilitar la entrada de los datos como string y la salida como objeto dinámico.

01 public class QueryRequest
02 {
03 public int Pagina { get; set; }
04 public int Registros { get; set; }
05
06 // input string - output dynamic
07 private string orden;
08 public dynamic Orden { get { return DeserializarJSon(orden); } set { orden = value; } }
09
10 // input string - output dynamic
11 private string filtro;
12 public dynamic Filtro { get { return DeserializarJSon(filtro); } set { filtro = value; } }
13
14 private dynamic DeserializarJSon(string strJson)
15 {
16 var jss = new JavaScriptSerializer();
17 dynamic resultado;
18 try
19 {
20 resultado = jss.Deserialize(strJson);
21 }
22 catch (Exception)
23 {
24 resultado = new { };
25 }
26 return resultado;
27 }
28
29 }

 

Ahora nuestro objeto es capaz de devolver un tipo anónimo al consultar la propiedad Filtro y Orden.

01 public IEnumerable FindFiltradoDinamico( QueryRequest datos )
02 {
03 //NoRM anonymous objects:
04 return GetRepository().GetCollection("Personas")
05 .Find(
06 datos.Filtro as object,
07 datos.Orden as object,
08 datos.Registros,
09 datos.Pagina * datos.Registros
10 );
11
12 }

 

Ahora si tenemos las consultas preparadas para aceptar parámetros dinámicos.

01 public ActionResult Index()
02 {
03 var datos = new QueryRequest()
04 {
05 Pagina = 0,
06 Registros = 10,
07 Filtro = " { Edad : { '$gt': 15 } } ", //mayor de 15 años
08 Orden = "{ Nombre : -1}" // 1 Ascendente - -1 Descendente
09 };
10
11 var f2 = repositoryPersona.FindFiltradoDinamico(datos);
12
13 return View();
14 }

 

 

Cross-Posting: http://mrubino.net

 

 

 

Posted: 5/12/2011 11:26 por Marc Rubiño | con no comments
Archivado en: ,