How to serialize/deserialize a DateTime stored inside an object field using DataContractJsonSerializer?(如何使用 DataContractJsonSerializer 序列化/反序列化存储在对象字段中的 DateTime?)
问题描述
我使用以下类通过两个 ASP.NET 服务交换 JSON 数据:
I use the following class to exchange JSON data over two ASP.NET services :
[DataContract]
public class Filter
{
   [DataMember]
   public string Name {get; set;}
   [DataMember]
   public FilterOperator Operator {get; set;}
   [DataMember]
   public object Value {get; set;}    
}
问题来了:如果我在 Value 中设置了一个 DateTime,它将被反序列化为字符串:
Here is the problem : if I set a DateTime inside Value, it will be deserialized as string : 
Value = "/Date(1476174483233+0200)/"
这可能是因为反序列化器在最初序列化时不知道值的类型:
This is probably because deserializer has no clue to know what was the type of the value when serialized initially :
JSON = {"Value":"/Date(1476174483233+0200)/"}
如 此处所述,DataContractJsonSerializer借助 __type 属性支持多态性.
As explained here, DataContractJsonSerializer supports polymorphism, with the help of the __type property.
我尝试在类的顶部添加 [KnownType(typeof(DateTime))] 属性,但没有帮助.
I have tried to add [KnownType(typeof(DateTime))] attribute on the top of the class but it does not help.
但是,如果我在 Value 属性中设置一个 Tuple (以及类上的相应 KnownType 属性),它就可以工作(它正确反序列化的值):
However if I set a Tuple<DateTime> inside Value property (and the appropriate KnownType attribute on the class), it works (the value it deserialized properly) :
Value = {(10/11/2016 10:49:30 AM)}
在 JSON 内部,发出 __type
Inside JSON, __type is emited
JSON = {
     "Value": {
        "__type" : "TupleOfdateTime:#System",
        "m_Item1" : "/Date(1476175770028+0200)/"
     }
}
有没有办法强制 DataContractJsonSerializer 发出适当的信息以正确序列化/反序列化 DateTime (这意味着我在序列化后得到了一个 DateTime而不是字符串)?
Is there a way to force DataContractJsonSerializer to emit proper information to serialize/deserialize DateTime properly (which mean I got a DateTime after serialization instead of a string) ? 
我尝试在 DataContractJsonSerializerSettings 中设置 EmitTypeInformation = EmitTypeInformation.Always 但没有帮助.
I have try to set EmitTypeInformation = EmitTypeInformation.Always in DataContractJsonSerializerSettings but it does not help.
推荐答案
问题是 DataContractJsonSerializer 只为对应的类型插入多态类型提示属性 "__type"到 JSON 对象 - 由 { 和 } 包围的一组无序的名称/值对.如果类型映射到其他任何东西(即 JSON 数组或原语),则没有地方可以插入类型提示.此限制记录在 独立 JSON 序列化中:
The problem is that DataContractJsonSerializer only inserts a polymorphic type hint property "__type" for types that correspond to a JSON object - an unordered set of name/value pairs surrounded by { and }.  If the type maps to anything else (i.e. a JSON array or primitive) then there is no place for a type hint to be inserted.  This restriction is documented in Stand-Alone JSON Serialization:
类型提示仅适用于复杂类型
没有办法为非复杂类型发出类型提示.例如,如果操作具有 Object 返回类型但返回 Circle,则 JSON 表示可以如前所示,并保留类型信息.但是,如果返回 Uri,则 JSON 表示是一个字符串,并且用于表示 Uri 的字符串的事实将丢失.这不仅适用于原始类型,也适用于集合和数组.
There is no way to emit a type hint for non-complex types. For example, if an operation has an Object return type but returns a Circle, the JSON representation can be as shown earlier and the type information is preserved. However, if Uri is returned, the JSON representation is a string and the fact that the string used to represent a Uri is lost. This applies not only to primitive types but also to collections and arrays.
因此,您需要做的是修改您的 Filter 类,以序列化和反序列化其值的通用代理对象,该对象封装了值的类型信息,就像 Json.Net 的这个问题:
Thus what you will need to do is to modify your Filter class to serialized and deserialized a generic surrogate object for its value that encapsulates the value's type information, along the lines the one in this question for Json.Net:
[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 将如下所示:
Now your JSON will look something like:
{
  "TypedValue": {
    "__type": "TypedSurrogateOfdateTime:#Question39973917",
    "Value": "/Date(1476244800000)/"
  }
}
                        这篇关于如何使用 DataContractJsonSerializer 序列化/反序列化存储在对象字段中的 DateTime?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何使用 DataContractJsonSerializer 序列化/反序列化存储在对象字段中的 DateTime?
				
        
 
            
        - 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
 - WebMatrix WebSecurity PasswordSalt 2022-01-01
 - 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
 - MoreLinq maxBy vs LINQ max + where 2022-01-01
 - C# 中多线程网络服务器的模式 2022-01-01
 - 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
 - Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
 - C#MongoDB使用Builders查找派生对象 2022-09-04
 - 输入按键事件处理程序 2022-01-01
 - 如何用自己压缩一个 IEnumerable 2022-01-01
 
						
						
						
						
						
				
				
				
				