NJsonSchema未校验数据类型:age字段类型不符却校验通过
JSON Schema校验字符串类型age未触发错误的问题排查与解决
问题描述
我在JSON Schema中为age属性指定了number类型,但传入字符串类型的age值(如下方示例JSON)时,NJsonSchema仍能校验通过,请问问题出在哪里?
测试JSON
{"name":"alex", "age":"14", "task":"anyTask"}
JSON Schema
{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "name": {"type":"string"}, "age": {"type": "number"}, "task": {"type": "string"} }, "required": [ "name", "age", "task" ] }
测试代码
string shema = "{\"$schema\": \"http://json-schema.org/draft-04/schema#\",\"type\": \"object\",\"properties\": {\"name\": {\"type\":\"string\"},\"age\": {\"type\": \"number\"},\"task\": {\"type\": \"string\"}},\"required\": [ \"name\", \"age\", \"task\" ]}"; JSchema schemaWithRequiredParameters = JSchema.Parse(shema); [TestCase("{\"name\":\"alex\", \"age\":\"14\", \"task\":\"anyTask\"}")] public async Task Valid_IncompleteInputJson_ShemaWithRequiredParameters_NotValid(string json) { Assert.IsFalse(await Validator.Valid(json, schemaWithRequiredParameters)); }
Validator类
public static async Task<bool> Valid(string json, JSchema schema) { string schemaJson = System.Text.Json.JsonSerializer.Serialize(schema); var jsonSchema = await NJsonSchema.JsonSchema.FromJsonAsync(schemaJson); var errors = jsonSchema.Validate(json); foreach (var error in errors) { Console.WriteLine(error); } return errors.Count == 0; }
问题原因
- NJsonSchema默认开启类型强制转换:NJsonSchema的
Validate方法默认启用AllowTypeCoercion选项,会自动将可转换的字符串(如"14")转为对应数字类型,因此字符串格式的数字会被判定为符合number类型要求,校验通过。 - Schema处理流程冗余且混用组件:代码中先使用Newtonsoft.Json的
JSchema.Parse解析Schema,再序列化后用NJsonSchema重新加载,这一步不仅多余,还可能导致Schema细节丢失或变形,增加不必要的风险。
解决方案
1. 关闭类型强制转换
调用Validate时传入ValidationSettings,明确禁用类型强制转换:
var errors = jsonSchema.Validate(json, new ValidationSettings { AllowTypeCoercion = false });
2. 简化Schema处理流程
直接使用NJsonSchema解析Schema字符串,避免混用Newtonsoft的JSchema组件:
- 修改测试代码中的Schema初始化:
string schemaJson = "{\"$schema\": \"http://json-schema.org/draft-04/schema#\",\"type\": \"object\",\"properties\": {\"name\": {\"type\":\"string\"},\"age\": {\"type\": \"number\"},\"task\": {\"type\": \"string\"}},\"required\": [ \"name\", \"age\", \"task\" ]}"; var schemaWithRequiredParameters = await NJsonSchema.JsonSchema.FromJsonAsync(schemaJson);
- 修改Validator类,移除多余的序列化/反序列化步骤:
public static bool Valid(string json, NJsonSchema.JsonSchema schema) { var errors = schema.Validate(json, new ValidationSettings { AllowTypeCoercion = false }); foreach (var error in errors) { Console.WriteLine(error); } return errors.Count == 0; }
3. 调整测试方法逻辑
匹配修改后的Validator,简化异步流程:
[TestCase("{\"name\":\"alex\", \"age\":\"14\", \"task\":\"anyTask\"}")] public async Task Valid_IncompleteInputJson_SchemaWithRequiredParameters_NotValid(string json) { var schema = await NJsonSchema.JsonSchema.FromJsonAsync(schemaJson); Assert.IsFalse(Validator.Valid(json, schema)); }
内容的提问来源于stack exchange,提问作者ggg
相关产品推荐
相关产品推荐

