用自己电脑做网站,凡科互动自动答题,网站开发保密合同,大鱼直播使用 JsonSchema 验证 API 的返回格式Intro最近我们的 API 提供给了别的团队的小伙伴用#xff0c;按照他们的需求做了接口的改动#xff0c;API 返回的数据结构有一些变化#xff0c;我们提供的接口有缓存#xff0c;数据库更新之后不会马上刷新#xff0c;于是就想验证一… 使用 JsonSchema 验证 API 的返回格式Intro最近我们的 API 提供给了别的团队的小伙伴用按照他们的需求做了接口的改动API 返回的数据结构有一些变化我们提供的接口有缓存数据库更新之后不会马上刷新于是就想验证一下数据是不是已经更新成最新的版本都更新好了之后就告诉别的团队的小伙伴做集成那么如何来验证是不是最新版本 API 呢现在我们的 API 基本上都是 JSON于是就想尝试使用 Json Schema 来验证我们的 APIWhatJson 是 JavaScript Object Notation 的缩写它是一种简化的数据交换格式是目前互联网服务间进行数据交换最常见的一种交换格式具有简洁、可读性好等特点。Json Schema 是用来定义 json 数据约束的一个标准可以清晰的描述JSON数据的结构是一种描述JSON数据的JSON数据。。根据这个约定模式交换数据的双方可以理解 json 数据的要求和约束也可以据此对数据进行验证保证数据交换的正确性。Why为什么我们要使用 JSON schema 呢在我们日常的使用中你也可以已经在使用了只是没有察觉我们在编辑一些 JSON 配置文件的时候有时候会有一些提示自动提示匹配的属性名这其实就是 Json shcema 带来的好处一些比较知名的项目的配置文件大多会提供一个自己的 json schema这不仅仅会为开发者们带来配置的便利也会便于实现 json 格式的校验总结一下 Json Schema 能够带来的好处智能提示 json-schema-lint格式校验自动化测试Mock 数据生成基于 schema 的数据生成支持 Json-Schema 的编辑器有很多Android StudioCLionIntelliJ IDEAJSONBuddyNeovimPhpStormPyCharmReSharperRiderRubyMineVisual Studio 2013Visual Studio CodeVisual Studio for MacWebStorm...Sample对于下面这样一段 json{productId: 1,productName: A green door,price: 12.50,tags: [ home, green ]
}JsonSchema 示例{$schema: https://json-schema.org/draft/2020-12/schema, // schema 规范版本可以没有$id: https://example.com/product.schema.json, // json schema 地址可以没有title: Product, // json schema 的标题信息可以没有description: A product from Acmes catalog, // json schema 的描述信息可以没有type: object, // 数据类型properties: { // 对象属性信息productId: { //属性名称description: The unique identifier for a product, // 属性描述type: integer // 属性类型},productName: { //属性名称description: Name of the product, // 属性描述type: string // 属性类型},price: { //属性名称description: The price of the product, // 属性描述type: number, // 属性类型exclusiveMinimum: 0 // 约束最小值不能小于0},tags: { // 属性名称description: Tags for the product, // 属性描述type: array, // 属性类型items: {type: string // 属性类型},minItems: 1, // 约束条件至少要有一个元素uniqueItems: true // 不能有重复项}},required: [ productId, productName, price ] // 必须的属性不存在则不符合 schema 的约束
}JSON Schema 的核心定义了以下基本类型stringnumberintegerobjectarray布尔值null除了上面的这些验证类型还有很多验证具体可以参考https://json-schema.org/draft/2020-12/json-schema-validation.htmlPracetice我选择的是 JsonSchema.Net这个是基于 System.Text.Json 来实现的一个 Json schema 的扩展使用起来也还好上手也比较简单构建 json schema 的简单示例var jsonSchema new JsonSchemaBuilder().Properties((name, new JsonSchemaBuilder().Type(SchemaValueType.String).MinLength(1).MaxLength(10)),(age, new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum(1))).Required(name).Build();这个示例构建了一个简单的 json 对象这个对象有两个属性一个 name 一个 age其中 name 是必须的属性name 是一个最小长度为1最大长度为 10 的字符串age 是一个最小值为 1 的数字除了使用 JsonSchemaBuilder 自己构建一个 json schema现在有很多在线的基于一段 json 自动生成 json schema 的工具我们也可以从一个 json schema 文件或者一个 Stream或者一段 schema 文本来获取一个 json schema本质就是读取一段 json 反序列成了一个 json schema 对象const string testJsonSchema
{$schema: https://json-schema.org/draft/2020-12/schema,type: object,properties: {Data: {type: array,items:{type: object,properties: {NoticeTitle: {type: string},NoticeCustomPath: {type: string},NoticePublishTime: {type: string}},required: [NoticeTitle,NoticeCustomPath,NoticePublishTime]}},PageNumber: {type: integer},PageSize: {type: integer},TotalCount: {type: integer},PageCount: {type: integer},Count: {type: integer}},required: [Data,PageNumber,PageSize,TotalCount,PageCount,Count]
}
;
var schema JsonSchema.FromText(testJsonSchema);有了 json schema 之后我们就可以用来验证 json 是否合法了JsonSchema 中有一个 ValidationResults Validate(JsonElement root, ValidationOptions? options null) 的方法在 2.2.0 之前的版本你需要将 json 转换为 JsonElement 来进行验证下面是文档给出的示例你需要先获取获取一个 JsonDocument然后使用 JsonDocument 的 RootElement 来验证JsonSchema schema new JsonSchemaBuilder().Properties((myProperty, new JsonSchemaBuilder().Type(SchemaValueType.String).MinLength(10))).Required(myProperty);
var emptyJson JsonDocument.Parse({}).RootElement;
var booleanJson JsonDocument.Parse({\myProperty\:false}).RootElement;
var stringJson JsonDocument.Parse({\myProperty\:\some string\}).RootElement;
var shortJson JsonDocument.Parse({\myProperty\:\short\}).RootElement;
var numberJson JsonDocument.Parse({\otherProperty\:35.4}).RootElement;
var nonObject JsonDocument.Parse(\not an object\).RootElement;var emptyResults schema.Validate(emptyJson);
var booleanResults schema.Validate(booleanJson);
var stringResults schema.Validate(stringJson);
var shortResults schema.Validate(shortJson);
var numberResults schema.Validate(numberJson);
var nonObjectResults schema.Validate(nonObject);感觉这样太不方便于是就写了两个扩展方法来方便直接从 JsonDocument 和 string 来验证public static ValidationResults Validate(this JsonSchema jsonSchema, JsonDocument jsonDocument, ValidationOptions? validationOptions null)
{return jsonSchema.Validate(jsonDocument.RootElement, validationOptions);
}public static ValidationResults Validate(this JsonSchema jsonSchema, string jsonString, ValidationOptions? validationOptions null)
{using var jsonDocument JsonDocument.Parse(jsonString);return jsonSchema.Validate(jsonDocument, validationOptions);
}并且提了 PR现在使用 2.2.0 版本就可以直接用了var validateResults schema.Validate({});
WriteLine(validateResults.IsValid);返回的结果中 IsValid 就代表了这个 Json 是否符合这个 json schema 的约束true 就是满足约束false 就是不满足默认的验证结果不会返回具体的错误信息你可以指定一个 ValidationOption指定 OutputFormat 为 Detailed 来返回具体的错误信息var schema JsonSchema.FromText(testJsonSchema);var validationOptions new ValidationOptions()
{OutputFormat OutputFormat.Detailed
};var invalidJson {Data: [{NoticeExternalLink: null}],PageNumber: 1,PageSize: 10,TotalCount: 5,PageCount: 1,Count: 5
}
;var validateResult schema.Validate(invalidJson, validationOptions);
WriteLine(validateResult.IsValid);
WriteLine(validateResult.Message);输出结果如下False
Required properties [NoticeTitle, NoticeCustomPath, NoticePublishTime] were not present验证 API 返回结果using var httpClient new HttpClient();
var result await httpClient.GetStringAsync(http://reservation.weihanli.xyz/api/notice);
validateResult schema.Validate(result, validationOptions);
WriteLine(validateResult.IsValid);
WriteLine(validateResult.Message);More这个库的作者除了实现了 JsonSchema 的支持还提供了对于 JsonPath、JsonPatch 等支持有需要的可以关注一下 https://github.com/gregsdennis/json-everything作者还提供了一个扩展库可以基于强类型的 Model 直接生成一个 schema不需要再自己构建 schema除了这个库你也可以选择别的库来实现Newtonsoft.Json.Schema 是基于 Newtosoft.Json 实现的 JsonSchema 的支持也可以尝试一下Referenceshttps://json-schema.org/https://www.tutorialspoint.com/json/json_schema.htmhttps://json-schema.org/learn/getting-started-step-by-step.htmlhttps://json-schema.org/draft/2020-12/json-schema-validation.htmlhttps://json-schema.apifox.cn/https://www.jsonschemavalidator.net/https://www.schemastore.org/json/https://github.com/gregsdennis/json-everythinghttps://github.com/gregsdennis/json-everything/pull/238https://github.com/WeihanLi/SamplesInPractice/blob/master/JsonSample/SystemTextJsonSample/JsonSchemaSample.cs