我有一个Asp.Net WebApi控制器,其操作如下:
public void Post([FromBody]object value)
现在,有时此value
参数将作为String
发送,其中包含ISO8601格式的日期,有时也会作为DateTime
。数据以JSON格式发送。
对于这两个选项中的每一个,我必须做不同的事情,所以我需要做出区分,但我总是得到DateTime
值。
我知道我的源DateTime
值在被发送到上述操作时被ISO8601格式的字符串序列化为JSON(我使用HttpClient
进行实际发送),因此我的行动无法区分这两者。
我的问题是,是否可以在发送的值中包含某种类型的提示,以便告诉我的WebApi端点正在发送哪种特定类型(并在反序列化的value
上强制执行该类型)。
答案 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