问题描述
我想序列化与图书馆 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!