c# - Can Json Schema Validation via Newtonsoft.Json.Schema validate VALUES? -
i have small sample. if json good, works correctly. if change "tag" (aka, property name), works correctly having invalid messages. if change value of guid non-guid-value, json schema validation not fail.
is there way fail validation guid value?
public class mycoolobject { public guid theuuid { get; set; } public int32 theinteger { get; set; } public datetime thedatetime { get; set; } }
and test method. when = 2 (and i'm setting string contain "notaguid-3333-3333-3333-333333333333"), when don't error messages like to.
private static void runjsonschemavalidate() { /* note, theuuid of type "string" , format "guid" */ string jsonschematext = @" { ""typename"": ""mycoolobject"", ""additionalproperties"": false, ""type"": ""object"", ""required"": [ ""theuuid"", ""theinteger"", ""thedatetime"" ], ""properties"": { ""theuuid"": { ""type"": ""string"", ""format"": ""guid"" }, ""theinteger"": { ""type"": ""integer"" }, ""thedatetime"": { ""type"": ""string"", ""format"": ""date-time"" } }, ""$schema"": ""http://json-schema.org/draft-04/schema#"" } "; newtonsoft.json.schema.jschema jschem = newtonsoft.json.schema.jschema.parse(jsonschematext); (int = 0; < 3; i++) { string jsoncontent = string.empty; switch (i) { case 1: /* bad json, change property name */ jsoncontent = @"{ ""theuuidxxx"": ""33333333-3333-3333-3333-333333333333"", ""theinteger"": 2147483647, ""thedatetime"": ""2017-08-22t15:32:10.7023008-04:00"" }"; break; case 2: /* bad json, change property value */ jsoncontent = @"{ ""theuuid"": ""notaguid-3333-3333-3333-333333333333"", ""theinteger"": 2147483647, ""thedatetime"": ""2017-08-22t15:32:10.7023008-04:00"" }"; break; case 3: /* bad json, bad integer */ jsoncontent = @"{ ""theuuid"": ""33333333-3333-3333-3333-333333333333"", ""theinteger"": notanumber, ""thedatetime"": ""2017-08-22t15:32:10.7023008-04:00"" }"; break; case 4: /* bad json, bad date */ jsoncontent = @"{ ""theuuid"": ""33333333-3333-3333-3333-333333333333"", ""theinteger"": 2147483647, ""thedatetime"": ""notadate"" }"; break; default: /* json */ jsoncontent = @"{ ""theuuid"": ""33333333-3333-3333-3333-333333333333"", ""theinteger"": 2147483647, ""thedatetime"": ""2017-08-22t15:32:10.7023008-04:00"" }"; break; } /* start meat of procedure */ newtonsoft.json.linq.jobject jobj = newtonsoft.json.linq.jobject.parse(jsoncontent); ilist<string> messages; bool valid = jobj.isvalid(jschem, out messages); /* endthe meat of procedure */ if (!valid) { string errormsg = "i=" + i.tostring() + ":" + string.join(",", messages); console.writeline(string.empty); console.writeline(string.empty); console.writeline(errormsg); } else { console.writeline(string.empty); console.writeline(string.empty); console.writeline("i=" + i.tostring() + ":" + "good json yes"); mycoolobject thisshouldworkwhenvalidationpasses = newtonsoft.json.jsonconvert.deserializeobject<mycoolobject>(jsoncontent); } console.writeline(string.empty); console.writeline("--------------------------------------------------"); console.writeline(string.empty); }
and packages
<?xml version="1.0" encoding="utf-8"?> <packages> <package id="newtonsoft.json" version="10.0.2" targetframework="net45" /> <package id="newtonsoft.json.schema" version="3.0.3" targetframework="net45" /> </packages>
so happening when i=2, json-schema passes, mycoolobject thisshouldworkwhenvalidationpasses throws exception....
i=2:good json yes
unhandled exception: newtonsoft.json.jsonserializationexception: error converting value "notaguid-3333-3333-3333-333333333333" type 'system.guid'. path 'theuuid', line 2, position 77. ---> system.argumentexception: not cast or convert system.string system.guid.
:(
i'm trying have json-schema fail earlier.
the end-game perform json-schema-validation without exceptions getting thrown. after "everything clear" try load objects. real stuff more complex, small demo shows issue(s).
i replaced "meat of procedure" below code
/* start meat of procedure */ newtonsoft.json.jsontextreader reader = new newtonsoft.json.jsontextreader(new system.io.stringreader(jsoncontent)); newtonsoft.json.schema.jschemavalidatingreader validatingreader = new newtonsoft.json.schema.jschemavalidatingreader(reader); validatingreader.schema = jschema.parse(schemajson); ilist<string> messages = new list<string>(); validatingreader.validationeventhandler += (o, a) => messages.add(a.message); newtonsoft.json.jsonserializer serializer = new newtonsoft.json.jsonserializer(); /* below issue code..you still try serialize object...and can throw exception */ mycoolobject p = serializer.deserialize<mycoolobject>(validatingreader); bool valid = !messages.any(); /* end meat of procedure */
but again, subject exceptions being thrown .. trying validate.
thanks jeroen mostert hint led me solution:
/* start meat of procedure */ ilist<string> deserializemessages = new list<string>(); /* first serialization issues */ mycoolobject p = jsonconvert.deserializeobject<mycoolobject>(jsoncontent, new jsonserializersettings { error = delegate (object sender, newtonsoft.json.serialization.erroreventargs args) { deserializemessages.add(args.errorcontext.error.message); args.errorcontext.handled = true; } }); ilist<string> jsonschemamessages = new list<string>(); bool jsonschemaisvalid = true; /* now, if there no serialization issues, @ schema */ if (!deserializemessages.any()) { newtonsoft.json.linq.jobject jobj = newtonsoft.json.linq.jobject.parse(jsoncontent); jsonschemaisvalid = jobj.isvalid(jschem, out jsonschemamessages); } ienumerable<string> allmessages = deserializemessages.union(jsonschemamessages); bool overallvalid = !allmessages.any(); /* end meat of procedure */
this gives me desired output situation:
i=0:good json yes
i=1:property 'theuuidxxx' has not been defined , schema not allow additional properties. path 'theuuidxxx', line 2, position 41.,required properties missing object: theuuid. path '', line 1, position 1.
i=2:error converting value "notaguid-3333-3333-3333-333333333333" type 'system.guid'. path 'theuuid', line 2, position 77.
i=3:unexpected character encountered while parsing value: o. path 'theinteger', line 3, position 41.,error parsing boolean value. path 'theinteger', line 3, position 42.
i=4:could not convert string datetime: notadate. path 'thedatetime', line 4, position 50.
press enter exit
i'm still wrapping head around little. in specific situation (where want response http request there json issue), works.
i won't mark "the answer" in case comes better.
note, changed loop < 5
for (int = 0; < 5; i++)
wiki
Comments
Post a Comment