我在使用Newtonsoft.Json.Schema库中的JSchemaValidatingReader时遇到了麻烦。问题是在JSON数据中验证日期字段。
给定这个模式和数据
var schemaString = "{"type":"object","properties":{"DueDate":{"required":true,"type":"string","format":"date"},"DateCompleted":{"required":true,"type":"string","format":"date-time"}}}";
var jsonData = "{"DueDate":"2015-08-25","DateCompleted":"2015-08-27T22:40:09.3749084-05:00"}";
我可以使用JToken.IsValid()方法正确地验证数据。这样的:
IList<string> errors = new List<string>();
var schema = JSchema.Parse(schemaString);
var json = JToken.Parse(jsonData);
var isValid = json.IsValid(schema, out errors); //isValid = true with no errors
但是,如果我尝试使用jschemvalidatingreader完成相同的事情,我会得到不同的结果。
var jsonReader = new JsonTextReader(new StringReader(jsonData));
var validatingReader = new JSchemaValidatingReader(jsonReader);
validatingReader.Schema = schema;
validatingReader.ValidationEventHandler += (o, a) => errors.Add(a.Path + ": " + a.Message);
var serializer = new JsonSerializer();
var hw = serializer.Deserialize<Homework>(validatingReader);
这将导致错误列表包含错误消息:
DueDate: String '2015-08-25T00:00:00'没有对格式'date'进行验证。路径'DueDate',第一行,位置23。
不知何故,时间组件被添加到日期字符串。这个错误可以通过设置JsonTextReader来避免。DateFormatString属性如下:
jsonReader.DateFormatString = "yyyy-MM-dd";
但是,这只会导致日期时间字段无法验证,并出现以下错误:
DateCompleted:字符串'2015-08-27'没有对格式'date-time'进行验证。路径'DateCompleted',第一行,位置75。
我做错了什么吗?还是jschemvalidatingreader实现有问题?
该问题是由JsonTextReader
+反序列化器将日期字符串解析为DateTimes引起的。一旦发生这种情况,原始字符串就会丢失,验证阅读器必须将DateTime转换回字符串,然后才能对其进行验证。这在IsValid中不会发生,因为它将所有内容读取为字符串。
目前有两个解决方案:
- 坚持使用IsValid验证。
- 在
JsonTextReader
上设置DateParseHandling为DateParseHandling.None
。日期将始终作为字符串读取,序列化程序将处理将它们转换为DateTime
我想,这是因为你有两种不同的日期格式,当JSchemaValidatingReader
只能处理你在jsonReader.DateFormatString