c# - 使用 ServiceStack.Text 序列化 ExpandoObject

标签 c# .net json servicestack

我正在尝试使用库 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"}]

为什么!怎么回事?

其次我怎样才能得到我想要的东西?

最佳答案

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[] 的支持内部。


附带说明一下,Microsoft 的 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);
    }

一个最终编辑:

您可以通过转动您的 ExpandoObject 来按照您想要的方式进行这项工作进入Dictionary<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 的人来说, 最好的办法就是把你的 ExpandoObject 包起来在DynamicJsonObject像这样:

    [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 一旦我解决了这个问题,我在这里发现了一个类似的问题:How to flatten an ExpandoObject returned via JsonResult in asp.net mvc?

关于c# - 使用 ServiceStack.Text 序列化 ExpandoObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11313078/

相关文章:

javascript - 重构 JSON 数据

javascript - 为什么webextension安装失败?

c# - 使用C#在xml文档中获取特定值

c# - 对象名称 'dbo.ApplicationUsers' 无效。?

c# - 处理计时器的最佳方法?

.net - .NET 3.5安装程序是否包括3.0 SP2?

php - 从 PHP 中的 JSON 数组获取值

c# - 编译一个dlib的.dll文件

c# - 如何调试代码分析自定义规则?

.net - 构造函数注入(inject)替代方案(温莎城堡)