我有一个小样本。如果我的Json好,它可以正常工作。如果我更改"标签" (也就是属性名称),它通过无效消息正常工作。如果我将Guid的值更改为非guid值,则Json Schema Validation不会失败。
有没有办法让Guid值验证失败?
public class MyCoolObject
{
public Guid TheUuid { get; set; }
public Int32 TheInteger { get; set; }
public DateTime TheDateTime { get; set; }
}
和我的测试方法。当i = 2时(我将字符串设置为包含" NOTAGUID-3333-3333-3333-333333333333"),那就是我没有得到像我想要的错误消息到。
private static void RunJsonSchemaValidate()
{
/* Note, the TheUuid is of type "string" and 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);
for (int i = 0; i < 3; i++)
{
string jsonContent = string.Empty;
switch (i)
{
case 1:
/* bad json, change the 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 the 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:
/* good json */
jsonContent = @"{
""TheUuid"": ""33333333-3333-3333-3333-333333333333"",
""TheInteger"": 2147483647,
""TheDateTime"": ""2017-08-22T15:32:10.7023008-04:00""
}";
break;
}
/* START THE MEAT OF THIS 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 THIS 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);
}
和包
<?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>
所以发生的事情是,当i = 2时,json-schema会通过,但是MyCoolObject thisShouldWorkWhenValidationPasses会抛出异常....
i = 2:好json是
未处理的异常:Newtonsoft.Json.JsonSerializationException:错误 转换价值&#34; NOTAGUID-3333-3333-3333-333333333333&#34;输入 &#39;的System.Guid&#39 ;. Path&#39; TheUuid&#39;,第2行,第77位.---&gt; System.ArgumentException:无法从System.String转换或转换 到System.Guid。
:(
我试图让json-schema更早失败。
最终游戏是执行json-schema-validation而不会抛出异常。然后&#34;一切都很清楚&#34;尝试加载对象。我的真实内容更复杂,但这个小型演示显示了问题。
我还 替换了 这个程序的主要内容&#34;使用以下代码
/* START THE MEAT OF THIS 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 is the issue with this code..you still try to serialize the object...and that can throw an exception */
MyCoolObject p = serializer.Deserialize<MyCoolObject>(validatingReader);
bool valid = !messages.Any();
/* END THE MEAT OF THIS PROCEDURE */
但同样,这可能会被抛出异常......试图验证。
答案 0 :(得分:1)
感谢Jeroen Mostert的提示,这使我得到了这个解决方案:
/* START THE MEAT OF THIS PROCEDURE */
IList<string> deserializeMessages = new List<string>();
/* first get any 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, only if there were no serialization issues, look at the 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 THE MEAT OF THIS PROCEDURE */
这为我提供了这种情况所需的输出:
i = 0:好json是
i = 1:属性&#39; TheUuidXXX&#39;尚未定义,架构没有 允许其他属性。 Path&#39; TheUuidXXX&#39;,第2行,位置 41.,对象缺少必需的属性:TheUuid。路径&#39;&#39;,第1行,第1位。
i = 2:转换值时出错&#34; NOTAGUID-3333-3333-3333-333333333333&#34;至 输入&#39; System.Guid&#39;。 Path&#39; TheUuid&#39;,第2行,第77位。
i = 3:解析值时遇到意外的字符:o。路径 &#39; TheInteger&#39;,第3行,第41位,错误解析布尔值。路径 &#39; TheInteger&#39;,第3行,第42位。
i = 4:无法将字符串转换为DateTime:NOTADATE。路径 &#39; TheDateTime&#39;,第4行,第50位。
按ENTER键退出
我仍然把头环绕着它。但是在我的特定情况下(我想立即回复http请求有一个json问题),它可以工作。
我没有将此标记为&#34;答案&#34;如果有人想出更好的东西。
注意,我将我的i for循环改为&lt; 5
for (int i = 0; i < 5; i++)