序列化ExpandoObject与ServiceStack.Text(Serializing Exp

2019-09-19 00:51发布

我试图序列与库对象ServiceStack.Text 。 这工作

using System.Dynamic;
using ServiceStack.Text;
var x = new {Value= 10, Product = "Apples"};                
Console.WriteLine(JsonSerializer.SerializeToString(x));

我得到的,如我所料

{"Value":10,"Product":"Apples"}

然而

dynamic x = new ExpandoObject();
x.Value = 100;
x.Product = "Apples";
Console.WriteLine(JsonSerializer.SerializeToString(x));

我得到让我吃惊

[{"Key":"Value","Value":100},{"Key":"Product","Value":"Apples"}]

为什么! 这是怎么回事?

其次我怎样才能得到我想要什么?

Answer 1:

ExpandoObject实现IConnection<KeyValuePair>IEnumerable<KeyValuePair>

public sealed class ExpandoObject :
    IDynamicMetaObjectProvider,
    IDictionary<string, object>,
    ICollection<KeyValuePair<string, object>>,
    IEnumerable<KeyValuePair<string, object>>,
    IEnumerable, INotifyPropertyChanged

我的猜测是在内部,ServiceStack串行器处理ExpandoObject作为IEnumerable<KeyValuePair>因此它以串行化键/值对的JSON阵列。


这不同于你的第一个(工作)的代码片段,因为.NET实际上建立了数据的一种真正的(匿名)类,基本上它使:

public class SomeNameTheCompilerMakesUp {
    internal int Value { get; set; }
    internal string Product { get; set; }
}

为您自动,所以当它被发送到串行器,它正在与不动产真实的类,而ExpandoObject真的是由支持object[]内。


在一个侧面说明,微软的System.Web.Helpers.Json的工作方式。 该测试通过了:

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

最后一个编辑:

你可以使这项工作要通过转动你的方式ExpandoObjectDictionary<string, object> 。 需要说明的这个代码是,它的数据复制到一个字典,所以你必须在内存中2个副本(或略显不足,由于技术上的字符串可能被拘留)。

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

虽然,对于遇到此之后,并实际使用人System.Web.Helpers.Json ,更好的事情做的仅仅是换你ExpandoObjectDynamicJsonObject这样的:

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

答一旦我通过努力,我发现了一个类似的问题在这里: 如何扁平化的ExpandoObject通过JsonResult在asp.net mvc的退换吗?



文章来源: Serializing ExpandoObject with ServiceStack.Text