我想序列化与图书馆 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 真的是由 [对象] 内部。
在一个侧面说明,微软 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 mvc的返回?
更多推荐
序列化ExpandoObject与ServiceStack.Text
发布评论