ExpandoObject
implementa IConnection<KeyValuePair>
y IEnumerable<KeyValuePair>
:
public sealed class ExpandoObject :
IDynamicMetaObjectProvider,
IDictionary<string, object>,
ICollection<KeyValuePair<string, object>>,
IEnumerable<KeyValuePair<string, object>>,
IEnumerable, INotifyPropertyChanged
Mi conjetura es que internamente, el serializador ServiceStack está tratando el ExpandoObject
como IEnumerable<KeyValuePair>
, y por lo que serializa a una matriz JSON de pares clave/valor.
Esto difiere de la primera (de trabajo) fragmento de código .NET, porque en realidad construye una verdadera clase (anónimo) para sus datos, básicamente se hace:
public class SomeNameTheCompilerMakesUp {
internal int Value { get; set; }
internal string Product { get; set; }
}
de forma automática, por lo que cuando se se envía al serializador, está trabajando con una clase real con propiedades reales, mientras que el ExpandoObject
está realmente respaldado por un object[]
internamente.
En una nota lateral, de Microsoft System.Web.Helpers.Json
se comporta de la misma manera. Esta prueba pasa:
[TestMethod]
public void ExpandoObjectSerializesToJsonArray()
{
dynamic anonType = new { Value = 10, Product = "Apples" };
dynamic expando = new ExpandoObject();
expando.Value = 10;
expando.Product = "Apples";
var anonResult = System.Web.Helpers.Json.Encode(anonType);
var expandoResult = System.Web.Helpers.Json.Encode(expando);
Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", anonResult);
Assert.AreEqual("[{\"Key\":\"Value\",\"Value\":10},{\"Key\":\"Product\",\"Value\":\"Apples\"}]", expandoResult);
}
Una edición final:
Puede que esto funcione de la manera deseada por convertir su ExpandoObject
en un Dictionary<string, object>
. La advertencia de este código es que duplica los datos en un diccionario, por lo que tiene 2 copias en la memoria (o un poco menos que, ya que técnicamente las cadenas podrían estar internados).
[TestMethod]
public void TestMethod1()
{
dynamic expando = new ExpandoObject();
expando.Value = 10;
expando.Product = "Apples";
// copy expando properties to dictionary
var dictionary = ((ExpandoObject)expando).ToDictionary(x => x.Key, x => x.Value);
var expandoResult = System.Web.Helpers.Json.Encode(expando);
var dictionaryResult = System.Web.Helpers.Json.Encode(dictionary);
Assert.AreEqual("[{\"Key\":\"Value\",\"Value\":10},{\"Key\":\"Product\",\"Value\":\"Apples\"}]", expandoResult);
Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", dictionaryResult);
}
Aunque, para cualquier persona que viene a través de esta tarde, y es en realidad el uso System.Web.Helpers.Json
, mejor que puede hacer es simplemente envolver su ExpandoObject
en un DynamicJsonObject
así:
[TestMethod]
public void TestMethod1()
{
dynamic expando = new ExpandoObject();
expando.Value = 10;
expando.Product = "Apples";
var dictionaryResult = System.Web.Helpers.Json.Encode(new DynamicJsonObject(expando));
Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", dictionaryResult);
}
Ans vez que trabajé a través de eso, encontré una pregunta similar aquí: How to flatten an ExpandoObject returned via JsonResult in asp.net mvc?
Parece que el serializador está malinterpretando su estructura de datos ... ¿podría publicar la estructura? –
Si instala ServiceStack.Text, debería poder ejecutar mi código arriba (repitiendo las instrucciones using). –