本文介绍了序列化ExpandoObject与ServiceStack.Text的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想序列化与图书馆 ServiceStack.Text 的对象。这适用

I am trying to serialize objects with the library ServiceStack.Text . This works

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

我得到的,因为我希望

I get, as I expect

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

然而

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

我得到我吃惊的是

I get to my surprise

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

为什么!这是怎么回事?

Why! What's going on?

第二我怎么能得到我想要什么?

推荐答案

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&LT; KeyValuePair&GT; ,和所以它系列化,以键/值对的JSON数组。

My guess is that internally, the ServiceStack serializer is treating the ExpandoObject as an IEnumerable<KeyValuePair>, and so it serializes to a JSON array of key/value pairs.

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

This differs from your first (working) code snippet because .NET actually builds a real (anonymous) class for your data, basically it makes:

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

自动为您,所以当它被发送到串行化器,它正在与一个真正的类不动产,而 ExpandoObject 真的是由<$支持C $ C> [对象] 内部。

在一个侧面说明,微软 System.Web.Helpers.Json 进行同样的操作。该测试通过:

On a side-note, Microsoft's System.Web.Helpers.Json behaves the same way. This test passes:

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


最后一个编辑:


One final edit:

您可以使这项工作要通过旋转的方式你的 ExpandoObject 词典&LT;字符串,对象&gt; 。需要说明的这个code是它复制数据到一本字典,让你有2份内存(或略小于,由于技术上的弦可能会扣留)。

You can make this work the way you want by turning your ExpandoObject into a Dictionary<string, object>. The caveat to this code is that it duplicates the data into a dictionary, so you have 2 copies in memory (or slightly less than, since technically the strings might be interned).

    [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 ,更好的事情要做的只是包装你的 ExpandoObject DynamicJsonObject 是这样的:

Although, for anyone that comes across this later, and is actually using System.Web.Helpers.Json, the better thing to do is just wrap your ExpandoObject in a DynamicJsonObject like this:

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

答一次,我通过努力,我发现了一个类似的问题在这里:How扁平化的ExpandoObject通过JsonResult在asp.net mvc的返回?

这篇关于序列化ExpandoObject与ServiceStack.Text的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 13:43