我正在尝试使用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个副本(或少于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/