How to serialize/deserialize a DateTime stored inside an object field using DataContractJsonSerializer?

允我心安 提交于 2019-12-02 09:05:33

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:

Type Hints Apply Only to Complex Types

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.

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; }
}

Now your JSON will look something like:

{
  "TypedValue": {
    "__type": "TypedSurrogateOfdateTime:#Question39973917",
    "Value": "/Date(1476244800000)/"
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!