ASP.NET WebApi 2:禁用包含ISO8601 Date的字符串参数的反序列化

时间:2017-01-04 15:58:21

标签: asp.net json datetime asp.net-web-api iso8601

我有一个Asp.Net WebApi控制器,其操作如下:

public void Post([FromBody]object value)

现在,有时此value参数将作为String发送,其中包含ISO8601格式的日期,有时也会作为DateTime。数据以JSON格式发送。

对于这两个选项中的每一个,我必须做不同的事情,所以我需要做出区分,但我总是得到DateTime值。

我知道我的源DateTime值在被发送到上述操作时被ISO8601格式的字符串序列化为JSON(我使用HttpClient进行实际发送),因此我的行动无法区分这两者。

我的问题是,是否可以在发送的值中包含某种类型的提示,以便告诉我的WebApi端点正在发送哪种特定类型(并在反序列化的value上强制执行该类型)。

1 个答案:

答案 0 :(得分:0)

最终通过实施自定义JsonConverter来解决此问题,该自定义Newtonsoft.Json将字符串值与类型提示序列化(类似于MetadataPropertyHandling JsonSerializerSettings public class DateStringTypeConservingConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsAssignableFrom(typeof(string)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.ReadFrom(reader); var typeMetadata = token["$type"]; if (typeMetadata?.Value<string>() == typeof(string).FullName) { return token.Value<string>("$value"); } // Default behavior return serializer.Deserialize(reader, objectType); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is string) { WriteJsonStringWithType(writer, value as string); } else { // Default behavior serializer.Serialize(writer, value); } } // Write the given string to the given JSON writer with type info: // { $type: "System.String", $value: "<string content>" } private void WriteJsonStringWithType(JsonWriter writer, string value) { writer.WriteStartObject(); writer.WritePropertyName("$type"); writer.WriteValue(typeof(string).FullName); writer.WritePropertyName("$value"); writer.WriteValue(value); writer.WriteEndObject(); } } 设置)。

这是实现技巧的实现:

    static void Main(string[] args)
    {
        var dateString = new Wrapper
        {
            Value = "2017-01-08T21:24:48.114Z"
        };

        var converters = new JsonConverter[] { new DateStringTypeConservingConverter() };
        var serializedDateString = JsonConvert.SerializeObject(dateString, new JsonSerializerSettings
        {
            Converters = converters
        });

        var deserializedDateString = 
            JsonConvert.DeserializeObject<Wrapper>(serializedDateString, converters);

        // Output: System.String
        Console.WriteLine($"The type of deserialized value is: { deserializedDateString.Value.GetType() }");

        Console.ReadKey();
    }

    class Wrapper
    {
        public object Value { get; set; }
    }

还有一点用法示例:

asset/javascript