如何使用DataContractJsonSerializer序列化/反序列化存储在对象字段中的DateTime
本文关键字:字段 对象 DateTime 存储 DataContractJsonSerializer 何使用 序列化 反序列化 | 更新日期: 2023-09-27 18:12:36
我使用下面的类在两个ASP上交换JSON数据。. NET服务:
[DataContract]
public class Filter
{
[DataMember]
public string Name {get; set;}
[DataMember]
public FilterOperator Operator {get; set;}
[DataMember]
public object Value {get; set;}
}
这里是问题:如果我在Value
中设置了DateTime
,它将被反序列化为字符串:
Value = "/Date(1476174483233+0200)/"
这可能是因为反序列化器不知道初始序列化时值的类型:
JSON = {"Value":"'/Date(1476174483233+0200)'/"}
如本文所述,在__type
属性的帮助下,DataContractJsonSerializer
支持多态性。
我试图在类的顶部添加[KnownType(typeof(DateTime))]
属性,但它没有帮助。
然而,如果我在Value
属性中设置Tuple<DateTime>
(以及类上的适当KnownType
属性),它会工作(它正确反序列化的值):
Value = {(10/11/2016 10:49:30 AM)}
在JSON内部,发出__type
JSON = {
"Value": {
"__type" : "TupleOfdateTime:#System",
"m_Item1" : "'/Date(1476175770028+0200)'/"
}
}
是否有一种方法可以强制DataContractJsonSerializer
发出适当的信息来正确地序列化/反序列化DateTime
(这意味着我在序列化后得到了DateTime
而不是字符串)?
我尝试在DataContractJsonSerializerSettings
中设置EmitTypeInformation = EmitTypeInformation.Always
,但它没有帮助。
问题是DataContractJsonSerializer
仅为对应于JSON对象的类型插入多态类型提示属性"__type"
-由{
和}
包围的无序名称/值对集。如果类型映射到其他任何东西(即JSON数组或原语),那么就没有地方插入类型提示。这个限制记录在独立JSON序列化中:
类型提示仅适用于复杂类型
没有办法为非复杂类型发出类型提示。例如,如果一个操作有一个Object返回类型,但是返回一个Circle,那么JSON表示可以如前面所示,并且类型信息被保留。但是,如果返回Uri,则JSON表示是一个字符串,并且丢失了用于表示Uri的字符串这一事实。这不仅适用于基本类型,也适用于集合和数组。
因此,您需要做的是修改Filter
类,为其值序列化和反序列化一个通用代理对象,该对象封装了值的类型信息,就像这个问题中的Json一样。净:
[DataContract]
public class Filter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public FilterOperator Operator { get; set; }
[IgnoreDataMember]
public object Value { get; set; }
[DataMember]
TypedSurrogate TypedValue
{
get
{
return TypedSurrogate.CreateSurrogate(Value);
}
set
{
if (value is TypedSurrogate)
Value = ((TypedSurrogate)value).ObjectValue;
else
Value = value;
}
}
}
[DataContract]
// Include some well-known primitive types. Other types can be included at higher levels
[KnownType(typeof(TypedSurrogate<string>))]
[KnownType(typeof(TypedSurrogate<bool>))]
[KnownType(typeof(TypedSurrogate<byte>))]
[KnownType(typeof(TypedSurrogate<sbyte>))]
[KnownType(typeof(TypedSurrogate<char>))]
[KnownType(typeof(TypedSurrogate<short>))]
[KnownType(typeof(TypedSurrogate<ushort>))]
[KnownType(typeof(TypedSurrogate<int>))]
[KnownType(typeof(TypedSurrogate<long>))]
[KnownType(typeof(TypedSurrogate<uint>))]
[KnownType(typeof(TypedSurrogate<ulong>))]
[KnownType(typeof(TypedSurrogate<float>))]
[KnownType(typeof(TypedSurrogate<double>))]
[KnownType(typeof(TypedSurrogate<decimal>))]
[KnownType(typeof(TypedSurrogate<DateTime>))]
[KnownType(typeof(TypedSurrogate<Uri>))]
[KnownType(typeof(TypedSurrogate<Guid>))]
[KnownType(typeof(TypedSurrogate<string[]>))]
public abstract class TypedSurrogate
{
protected TypedSurrogate() { }
[IgnoreDataMember]
public abstract object ObjectValue { get; }
public static TypedSurrogate CreateSurrogate<T>(T value)
{
if (value == null)
return null;
var type = value.GetType();
if (type == typeof(T))
return new TypedSurrogate<T>(value);
// Return actual type of subclass
return (TypedSurrogate)Activator.CreateInstance(typeof(TypedSurrogate<>).MakeGenericType(type), value);
}
}
[DataContract]
public class TypedSurrogate<T> : TypedSurrogate
{
public TypedSurrogate() : base() { }
public TypedSurrogate(T value)
: base()
{
this.Value = value;
}
public override object ObjectValue { get { return Value; } }
[DataMember]
public T Value { get; set; }
}
现在你的JSON看起来像这样:
{
"TypedValue": {
"__type": "TypedSurrogateOfdateTime:#Question39973917",
"Value": "/Date(1476244800000)/"
}
}