2016-10-11 76 views
0

我用下面的類在兩個ASP.NET服務交換JSON數據:如何使用DataContractJsonSerializer序列化/反序列化存儲在對象字段內的DateTime?

[DataContract] 
public class Filter 
{ 
    [DataMember] 
    public string Name {get; set;} 

    [DataMember] 
    public FilterOperator Operator {get; set;} 

    [DataMember] 
    public object Value {get; set;}  
} 

這裏的問題是:如果我設置一個DateTimeValue,將反序列化字符串:

Value = "/Date(1476174483233+0200)/" 

這可能是因爲解串器沒有線索知道是值的類型最初連載時:

JSON = {"Value":"\/Date(1476174483233+0200)\/"} 

如解釋hereDataContractJsonSerializer支持多態性,在__type屬性的幫助下。

我試圖在課程頂部添加[KnownType(typeof(DateTime))]屬性,但它沒有幫助。

但是如果我設置了Tuple<DateTime>Value屬性(類上的適當KnownType屬性),它的工作原理(得當反序列化值):

Value = {(10/11/2016 10:49:30 AM)} 

裏面JSON,__type是emited

JSON = { 
    "Value": { 
     "__type" : "TupleOfdateTime:#System", 
     "m_Item1" : "\/Date(1476175770028+0200)\/" 
    } 
} 

有沒有辦法強制DataContractJsonSerializer發出正確的信息來序列化/反序列化DateTime正確(這意味着我得到了DateTime序列化後,而不是一個字符串)?

我嘗試在DataContractJsonSerializerSettings中設置EmitTypeInformation = EmitTypeInformation.Always,但它沒有幫助。

+0

可以修改'Filter'類? – dbc

+0

是的,它可以改變。 – tigrou

回答

1

的問題是,僅DataContractJsonSerializer插入對於對應於一個JSON對象類型的多態型提示屬性"__type" - 一組無序通過{}包圍的名稱/值對。如果類型映射到其他任何東西(即JSON數組或基元),那麼沒有地方可以插入類型提示。此限制記錄在Stand-Alone JSON Serialization

類型提示僅適用於複雜類型

沒有辦法爲:發射非複雜類型類型提示。例如,如果某個操作具有Object返回類型但返回了Circle,則JSON表示可以如前所示,並且類型信息將被保留。但是,如果返回Uri,那麼JSON表示形式就是一個字符串,並且用於表示Uri的字符串會丟失。這不僅適用於原始類型,還適用於集合和數組。

因此,你需要做的是改變你的Filter類序列化和反序列化它的價值,它封裝了值的類型信息的通用替代對象,沿線的一個在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看起來像:

{ 
    "TypedValue": { 
    "__type": "TypedSurrogateOfdateTime:#Question39973917", 
    "Value": "/Date(1476244800000)/" 
    } 
} 
相關問題