使用Newtonsoft.Json.Schema生成Schema时DateTime日期格式验证失败问题
解决Newtonsoft.Json.Schema验证自定义日期格式失败的问题
这问题我太熟了——你遇到的核心矛盾是:Newtonsoft.Json.Schema默认会给DateTime类型生成"format": "date-time"的Schema规则,但你的ShortDateConverter会把日期序列化成纯日期格式(比如"2024-05-20"),和默认要求的带时分秒的date-time格式不匹配,所以验证环节直接报错。
下面给你一套完整的解决办法:
1. 自定义Schema生成器,适配ShortDateConverter
我们需要继承JSchemaGenerator,重写它的Schema生成逻辑,当遇到标记了ShortDateConverter的DateTime属性时,生成对应纯日期格式的Schema规则,而不是默认的date-time。
代码示例:
using Newtonsoft.Json; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Schema.Generation; using System; using System.Reflection; public class CustomSchemaGenerator : JSchemaGenerator { protected override JSchema GenerateSchema(Type type, SchemaGenerationProviderContext context) { // 检查当前处理的属性是否带有ShortDateConverter特性 var jsonConverterAttr = context.Member?.GetCustomAttribute<JsonConverterAttribute>(); if (type == typeof(DateTime) && jsonConverterAttr?.ConverterType == typeof(ShortDateConverter)) { // 生成标准ISO 8601日期格式的Schema:类型为string,format为date return new JSchema { Type = JSchemaType.String, Format = "date" }; } // 其他类型和属性沿用默认生成逻辑 return base.GenerateSchema(type, context); } }
2. 使用自定义生成器创建Schema
接下来,替换默认的生成器为我们自定义的版本,生成适配你日期格式的Schema:
var schemaGenerator = new CustomSchemaGenerator(); JSchema validSchema = schemaGenerator.Generate(typeof(SomeClass));
3. 特殊情况:如果你的日期格式不是标准ISO 8601
如果你的ShortDateConverter输出的是自定义格式(比如MM/dd/yyyy),那上面的format: "date"就不适用了,需要改用pattern规则来匹配你的自定义格式:
// 在CustomSchemaGenerator的对应逻辑里替换成: return new JSchema { Type = JSchemaType.String, Pattern = @"^\d{2}/\d{2}/\d{4}$" // 匹配MM/dd/yyyy格式,可根据你的实际格式调整正则 };
验证测试
现在用生成的Schema验证序列化后的JSON,比如:
var someObj = new SomeClass { SomeDate = new DateTime(2024, 5, 20) }; string json = JsonConvert.SerializeObject(someObj); // 输出应该是{"someDate":"2024-05-20"} var schemaValidatingReader = new JSchemaValidatingReader(new JsonTextReader(new StringReader(json))) { Schema = validSchema }; // 执行验证,如果没有抛出异常就是成功的 while (schemaValidatingReader.Read()) { }
这样就能解决Schema验证和自定义日期转换器的冲突问题了。
内容的提问来源于stack exchange,提问作者villuMal
相关产品推荐
相关产品推荐

