如何让 ServiceStack 序列化/反序列化具有正确类型的 expando 对象
Posted
技术标签:
【中文标题】如何让 ServiceStack 序列化/反序列化具有正确类型的 expando 对象【英文标题】:How to get ServiceStack to serialize / deserialize an expando object with correct types 【发布时间】:2012-11-22 21:38:02 【问题描述】:只是想弄清楚 servicestack.text 支持将 expando 对象序列化到 json 和从 json 序列化的能力。我知道expando 对象实现了一个IDictionary。当我序列化到 json 和从 json 序列化时,我无法在反序列化的 IDictionary 中获取正确的类型。由于 Json 本身不支持类型,并且 servicestack 有一个名为 JsConfig.IncludeTypeInfo 的设置,我希望它在序列化的 json 中包含类型信息,以使服务堆栈能够反序列化为另一端的正确类型(例如,没有小数位的小数被反序列化为 uint64)。
是否有强制 servicestack 使用 expando 对象正确反序列化与源相同的类型?
Ps:我不想使用 poco 对象来实现这一点,因为直到运行时我才知道对象的属性。
下面是一个快速测试,说明我的意思。
谢谢
/// <summary>
/// Test servicestack serialisation
/// I was expecting that IncludeTypeInfo=true would always add the type info
/// so when you deserialise into a IDictionary<string,object> servicerstack
/// would have enough information to convert to the expected type
/// </summary>
[Test]
public void TestDynamicSerialization()
JsConfig.Reset();
JsConfig.IncludeNullValues = true;
JsConfig.IncludeTypeInfo = true;
JsConfig.EmitCamelCaseNames = false;
JsConfig.ConvertObjectTypesIntoStringDictionary = true;
JsConfig.PropertyConvention = JsonPropertyConvention.Lenient;
JsConfig.TryToParsePrimitiveTypeValues = true;
// create an expando object
dynamic obj = new ExpandoObject();
// cast as a idictionary and set two decimals, one with decimnal places and one without
var objDict = (IDictionary<string, object>)obj;
objDict["decimal1"] = 12345.222M;
objDict["decimal2"] = 12345M;
Assert.AreEqual(typeof(decimal), objDict["decimal1"].GetType());
Assert.AreEqual(typeof(decimal), objDict["decimal2"].GetType());
// serialise to json
var json = JsonSerializer.SerializeToString(obj);
//deserialise to a a IDictionary<string,object>
var deserialisedDict = JsonSerializer.DeserializeFromString<IDictionary<string, object>>(json);
// make sure we got the expected types
Assert.AreEqual(typeof(decimal), deserialisedDict["decimal1"].GetType());
Assert.AreEqual(typeof(decimal), deserialisedDict["decimal2"].GetType(), "Fails because type is UInt64 expected decimal");
【问题讨论】:
【参考方案1】:NuGet 上的 ServiceStack.Text 是一个 .NET 3.5 dll,没有对 Dynamic/Expando 的隐式支持。您仍然可以使用 JsonObject
动态解析 JSON。
在 ServiceStack.Text 的 .NET 4.0 构建中,您可以使用 DynamicJson
,它将对动态类中 JSON 对象的访问包装。
【讨论】:
我将反序列化更改为 JsonObject,但正如我所料,它不知道类型的正确类型,并且十进制字段是字符串类型。 var deserialisedDict = JsonSerializer.DeserializeFromString应该从@987654321 开始固定@ 小数默认会返回,除非您指定 TryToParseNumericType,在这种情况下您将获得最合适的数字类型。
【讨论】:
以上是关于如何让 ServiceStack 序列化/反序列化具有正确类型的 expando 对象的主要内容,如果未能解决你的问题,请参考以下文章
C# ServiceStack JsonSerializer 反序列化
使用带有 servicestack 的构造函数反序列化 json
使用 Servicestack.Text 进行 XML 反序列化
ServiceStack.Text JsonSerializer 无法反序列化其自己的序列化模式(类型定义应以 '' SerializationException 开头)