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

后端 未结 1 1323
一整个雨季
一整个雨季 2021-01-28 08:20

I use the following class to exchange JSON data over two ASP.NET services :

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


        
相关标签:
1条回答
  • 2021-01-28 08:29

    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)/"
      }
    }
    
    0 讨论(0)
提交回复
热议问题