Realmente me gusta al ExpandoObject
compilar un objeto dinámico del lado del servidor en tiempo de ejecución, pero tengo problemas para aplanar esto durante la serialización JSON. Primero, instancia el objeto:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
Hasta aquí todo bien. En mi controlador MVC, quiero enviar esto como un JsonResult, así que hago esto:
return new JsonResult(expando);
Esto serializa el JSON en el siguiente, para ser consumido por el navegador:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
PERO, lo que realmente me gustaría es ver esto:
{SomeProp: SomeValueOrClass}
Sé que puedo lograr esto si uso en dynamic
lugar de ExpandoObject
: JsonResult
es capaz de serializar las dynamic
propiedades y los valores en un solo objeto (sin negocios de clave o valor), pero la razón por la que necesito usar ExpandoObject
es porque no sé todos las propiedades que quiero en el objeto hasta el tiempo de ejecución , y hasta donde yo sé, no puedo agregar dinámicamente una propiedad a dynamic
sin usar un ExpandoObject
.
Puede que tenga que examinar el negocio "Clave", "Valor" en mi javascript, pero esperaba resolver esto antes de enviarlo al cliente. ¡Gracias por tu ayuda!
fuente
Respuestas:
También puede crear un JSONConverter especial que funcione solo para ExpandoObject y luego registrarlo en una instancia de JavaScriptSerializer. De esta manera, podría serializar matrices de expando, combinaciones de objetos expando y ... hasta que encuentre otro tipo de objeto que no se serialice correctamente ("de la manera que desee"), entonces crea otro convertidor o agrega otro tipo a éste. Espero que esto ayude.
Usando convertidor
fuente
NotImplementedException
agregar algo comoserializer.Deserialize<ExpandoObject>(json);
, @theburningmonk ofrece una solución que funcionó para mí.Usando JSON.NET puede llamar a SerializeObject para "aplanar" el objeto expando:
Saldrá:
En el contexto de un controlador ASP.NET MVC, el resultado se puede devolver utilizando el método Content:
fuente
Esto es lo que hice para lograr el comportamiento que está describiendo:
El costo es que está haciendo una copia de los datos antes de serializarlos.
fuente
ExpandoObject
le ofrece mucha más flexibilidad que un diccionario simple. Aunque el ejemplo anterior no lo demuestra, puede usar las características dinámicas delExpandoObject
para agregar las propiedades que desea tener en su JSON. UnDictioanry
objeto normal se convertirá a JSON sin ningún problema, por lo que al hacer la conversión, es una forma O (n) simple de poner la dinámica fácil de usarExpandoObject
en un formato que puede ser JSONificado. Sin embargo, tiene razón, el ejemplo anterior sería un uso rediculus deExpandoObject
; un simpleDictionary
sería mucho mejor.Resolví esto escribiendo un método de extensión que convierte el ExpandoObject en una cadena JSON:
Esto usa la excelente biblioteca Newtonsoft .
JsonResult se ve así:
Y esto se devuelve al navegador:
Y puedo usarlo en javascript haciendo esto (mencionado aquí ):
¡Espero que esto ayude!
fuente
Pude resolver este mismo problema usando JsonFx .
salida:
fuente
Llevé el proceso de aplanamiento un paso más allá y verifiqué los objetos de la lista, lo que elimina las tonterías del valor clave. :)
fuente
Esto puede no ser útil para usted, pero tenía un requisito similar, pero usé un SerializableDynamicObject
Cambié el nombre del diccionario a "Campos" y luego esto se serializa con Json.Net para producir json que se ve así:
{"Campos": {"Propiedad1": "Valor1", "Propiedad2": "Valor2", etc. donde Propiedad1 y Propiedad2 son propiedades agregadas dinámicamente, es decir, claves de diccionario
Sería perfecto si pudiera deshacerme de la propiedad adicional "Fields" que encapsula el resto, pero he solucionado esa limitación.
Respuesta movida de esta pregunta a pedido
fuente
Esta es una respuesta tardía, pero tuve el mismo problema y esta pregunta me ayudó a resolverlos. Como resumen, pensé que debería publicar mis resultados, con la esperanza de que acelere la implementación para otros.
Primero, el ExpandoJsonResult, del cual puede devolver una instancia en su acción. O puede anular el método Json en su controlador y devolverlo allí.
Luego, el convertidor (que admite tanto la serialización como la deserialización. Consulte a continuación un ejemplo de cómo deserializar).
Puede ver en la clase ExpandoJsonResult cómo usarlo para la serialización. Para deserializar, cree el serializador y registre el convertidor de la misma manera, pero use
Un gran agradecimiento a todos los participantes aquí que me ayudaron.
fuente
Al devolver ExpandoObject dinámico de WebApi en ASP.Net 4, el formateador JSON predeterminado parece aplanar ExpandoObjects en un objeto JSON simple.
fuente
JsonResult
utilizaJavaScriptSerializer
que realmente deserializa (el concreto)Dictionary<string, object>
como desee.Hay una sobrecarga del
Dictionary<string, object>
constructor que tomaIDictionary<string, object>
.ExpandoObject
implementosIDictionary<string, object>
(creo que puedes ver a dónde voy aquí ...)ExpandoObject de un solo nivel
Una línea de código, usando todos los tipos integrados :)
ExpandoObjects anidados
Por supuesto, si está anidando
ExpandoObject
correos electrónicos, deberá convertirlos todos de forma recursiva en correos electrónicosDictionary<string, object>
:tu código final se convierte
fuente
Parece que el serializador está enviando el Expando a un Diccionario y luego serializándolo (por lo tanto, el negocio Clave / Valor). ¿Ha intentado deserializar como diccionario y luego volver a convertirlo en un Expando?
fuente
Simplemente tuve el mismo problema y descubrí algo bastante extraño. Si lo hago:
Funciona, pero solo si mi método usa el atributo HttpPost. Si uso HttpGet, obtengo un error. Entonces mi respuesta solo funciona en HttpPost. En mi caso, fue una llamada Ajax, por lo que pude cambiar HttpGet por HttpPost.
fuente