I'm having trouble using the JSchemaValidatingReader from the Newtonsoft.Json.Schema library. The issue is around validating date fields in JSON data.
Given this schema and data
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\"}";
I can validate the data correctly using the JToken.IsValid() method. Like this:
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
However, if I try to accomplish the same thing using JSchemaValidatingReader, I get a different result.
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);
This will result in the error list containing an error with the message:
DueDate: String '2015-08-25T00:00:00' does not validate against format 'date'. Path 'DueDate', line 1, position 23.
Somehow the time component is being added to the date string. This error can be avoided by setting the JsonTextReader.DateFormatString property like this:
jsonReader.DateFormatString = "yyyy-MM-dd";
However, this just causes date-time fields to not validate with this error:
DateCompleted: String '2015-08-27' does not validate against format 'date-time'. Path 'DateCompleted', line 1, position 75.
Am I doing something wrong? Or is there an issue with the JSchemaValidatingReader implementation?
The issue is caused by JsonTextReader + the deserializer parsing the date strings to DateTimes. Once that happens the original string is lost and the validating reader has to convert the DateTime back to a string before it can be validated. This doesn't happen with IsValid because it reads everything as a string.
Two solutions for now:
JsonTextReader set DateParseHandling to DateParseHandling.None. Dates will always be read as strings and the serializer will handle converting them to DateTimeIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With