什么是Json Schema ?

Json Schema是一种声明式语言,它可以用来标识Json的结构,数据类型和数据的具体限制,它提供了描述期望Json结构的标准化方法。

利用Json Schema, 你可以定义Json结构的各种规则,以便确定Json数据在各个子系统中交互传输时保持兼容和一致的格式。

一般来说,系统可以自己实现逻辑来判断当前json是否满足接口要求,比如是否某个字段存在,是否属性值是有效的。但当验证需求变得复杂后,比如有大量嵌套json结构,属性之间的复杂关联限制等等,则容易编写出考虑不全的验证代码。另外,当系统需要动态的json数据要求,比如先由用户自己决定他需要的json结构,然后系统根据用户表达的定制化json结构需求,帮助用户验证后续的json数据。这种系统代码编译时无法确定的json结构,就需要另一种解决方案。

Json Schema就是针对这种问题的比较自然的解决方案。它可以让你或你的用户描述希望的json结构和值的内容限制,有效属性,是否是required, 还有有效值的定义,等等。。利用Json Schema, 人们可以更好的理解Json结构,而且程序也可以根据你的Json Schema验证Json数据。

比如下面的一个简单例子,用.net下的Json Schema实现库LateApexEarlySpeed.Json.Schema进行Json数据的验证:

Json Schema (文件:schema.json):

{
"type": "object",
"properties": {
"propBoolean": {
"type": "boolean"
},
"propArray": {
"type": "array",
"uniqueItems": true
}
}
}

Json 数据 (文件:instance.json):

{
"propBoolean": true,
"propArray": [ 1, 2, 3, 4, 4 ]
}

C# 代码:

            string jsonSchema = File.ReadAllText("schema.json");
string instance = File.ReadAllText("instance.json"); var jsonValidator = new JsonValidator(jsonSchema);
ValidationResult validationResult = jsonValidator.Validate(instance); if (validationResult.IsValid)
{
Console.WriteLine("good");
}
else
{
Console.WriteLine($"Failed keyword: {validationResult.Keyword}");
Console.WriteLine($"ResultCode: {validationResult.ResultCode}");
Console.WriteLine($"Error message: {validationResult.ErrorMessage}");
Console.WriteLine($"Failed instance location: {validationResult.InstanceLocation}");
Console.WriteLine($"Failed relative keyword location: {validationResult.RelativeKeywordLocation}");
}

输出:

Failed keyword: uniqueItems
ResultCode: DuplicatedArrayItems
Error message: There are duplicated array items
Failed instance location: /propArray
Failed relative keyword location: /properties/propArray/uniqueItems

LateApexEarlySpeed.Json.Schema中文介绍

项目原始文档:https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema.Doc

中文文档:

LateApexEarlySpeed.Json.Schema是2023年12月发布的一个新的.net下的Json Schema实现库,基于截止到2023年12月为止最新版的Json schema - draft 2020.12。

Json Schema验证功能经过了official json schema test-suite for draft 2020.12的测试。(部分排除的用例见下面的已知限制章节)

LateApexEarlySpeed.Json.Schema的主要特点是:

  • 基于微软.net下默认的System.Text.Json而非经典的Newtonsoft.Json
  • 使用简单
  • 和已有的知名且杰出的.net下的一些JsonSchema实现库相比,具有很好的性能 (在common case下,利用BenchmarkDotnet进行的性能测试)。用户请根据自己的使用场景进行性能验证

该实现库之后可能会transfer成开源项目。

基础用法

安装Nuget package

Install-Package LateApexEarlySpeed.Json.Schema
string jsonSchema = File.ReadAllText("schema.json");
string instance = File.ReadAllText("instance.json"); var jsonValidator = new JsonValidator(jsonSchema);
ValidationResult validationResult = jsonValidator.Validate(instance); if (validationResult.IsValid)
{
Console.WriteLine("good");
}
else
{
Console.WriteLine($"Failed keyword: {validationResult.Keyword}");
Console.WriteLine($"ResultCode: {validationResult.ResultCode}");
Console.WriteLine($"Error message: {validationResult.ErrorMessage}");
Console.WriteLine($"Failed instance location: {validationResult.InstanceLocation}");
Console.WriteLine($"Failed relative keyword location: {validationResult.RelativeKeywordLocation}");
Console.WriteLine($"Failed schema resource base uri: {validationResult.SchemaResourceBaseUri}");
}

输出信息

当json数据验证失败后,可以查看错误数据的具体信息:

  • IsValid: As summary indicator for passed validation or failed validation.

  • ResultCode: The specific error type when validation failed.

  • ErrorMessage: the specific wording for human readable message

  • Keyword: current keyword when validation failed

  • InstanceLocation: The location of the JSON value within the instance being validated. The value is a JSON Pointer.

  • RelativeKeywordLocation: The relative location of the validating keyword that follows the validation path. The value is a JSON Pointer, and it includes any by-reference applicators such as "$ref" or "$dynamicRef". Eg:

    /properties/width/$ref/minimum
  • SubSchemaRefFullUri: The absolute, dereferenced location of the validating keyword when validation failed. The value is a full URI using the canonical URI of the relevant schema resource with a JSON Pointer fragment, and it doesn't include by-reference applicators such as "$ref" or "$dynamicRef" as non-terminal path components. Eg:

    https://example.com/schemas/common#/$defs/count/minimum
  • SchemaResourceBaseUri: The absolute base URI of referenced json schema resource when validation failed. Eg:

    https://example.com/schemas/common

性能建议

尽可能的重用已实例化的JsonValidator实例(JsonValidator可以简单理解为代表一个json schema验证文档)来验证json数据,以便获得更高性能

外部json schema依赖的支持

除了自动支持当前schema文档内的引用关系,还支持外部json schema依赖:

  • 本地schema依赖文本
var jsonValidator = new JsonValidator(jsonSchema);
string externalJsonSchema = File.ReadAllText("schema2.json");
jsonValidator.AddExternalDocument(externalJsonSchema);
ValidationResult validationResult = jsonValidator.Validate(instance);
  • 远程schema url (实现库将访问网络来获得远程的schema)
var jsonValidator = new JsonValidator(jsonSchema);
await jsonValidator.AddHttpDocumentAsync(new Uri("http://this-is-json-schema-document"));
ValidationResult validationResult = jsonValidator.Validate(instance);

自定义keyword的支持

除了json schema specification中的标准keywords之外,还支持用户创建自定义keyword来实现额外的验证需求:

{
"type": "object",
"properties": {
"prop1": {
"customKeyword": "Expected value"
}
}
}
ValidationKeywordRegistry.AddKeyword<CustomKeyword>();
[Keyword("customKeyword")] // It is your custom keyword name
[JsonConverter(typeof(CustomKeywordJsonConverter))] // Use 'CustomKeywordJsonConverter' to deserialize to 'CustomKeyword' instance out from json schema text
internal class CustomKeyword : KeywordBase
{
private readonly string _customValue; // Simple example value public CustomKeyword(string customValue)
{
_customValue = customValue;
} // Do your custom validation work here
protected override ValidationResult ValidateCore(JsonInstanceElement instance, JsonSchemaOptions options)
{
if (instance.ValueKind != JsonValueKind.String)
{
return ValidationResult.ValidResult;
} return instance.GetString() == _customValue
? ValidationResult.ValidResult
: ValidationResult.CreateFailedResult(ResultCode.UnexpectedValue, "It is not my expected value.", options.ValidationPathStack, Name, instance.Location);
}
}
internal class CustomKeywordJsonConverter : JsonConverter<CustomKeyword>
{
// Library will input json value of your custom keyword: "customKeyword" to this method.
public override CustomKeyword? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Briefly:
return new CustomKeyword(reader.GetString()!);
} public override void Write(Utf8JsonWriter writer, CustomKeyword value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}

Format支持

目前实现库支持如下format:

  • uri
  • uri-reference
  • date
  • time
  • date-time
  • email
  • uuid
  • hostname
  • ipv4
  • ipv6
  • json-pointer
  • regex

Format 验证需要显式enable, 当验证数据时,请传入配置好的 JsonSchemaOptions:

jsonValidator.Validate(instance, new JsonSchemaOptions{ValidateFormat = true});

如果需要自定义format验证,可以实现一个FormatValidator子类并注册:

[Format("custom_format")] // this is your custom format name in json schema
public class TestCustomFormatValidator : FormatValidator
{
public override bool Validate(string content)
{
// custom format validation logic here...
}
} // register it globally
FormatRegistry.AddFormatType<TestCustomFormatValidator>();

Other extension usage doc is to be continued .

限制

  • 目前类库关注于验证,暂不支持annotation
  • 因为暂不支持annotation, 所以不支持如下keywords: unevaluatedProperties, unevaluatedItems
  • 目前不支持 content-encoded string

问题报告

欢迎把使用过程中遇到的问题和希望增加的功能发到github repo issue中

More doc is to be written

Json Schema简介和Json Schema的.net实现库 LateApexEarlySpeed.Json.Schema的更多相关文章

  1. Json Schema简介

    1. 引言 什么是Json Schema? 以一个例子来说明 假设有一个web api,接受一个json请求,返回某个用户在某个城市关系最近的若干个好友.一个请求的例子如下: { "city ...

  2. Json/Xml简介和处理模型

    JSON json简介 JSON是一种基于文本的数据交换格式,源自JavaScript,用于Web服务和其他连接的应用程序.以下部分介绍了JSON语法,JSON使用概述以及生成和解析JSON的最常用方 ...

  3. Apache Avro & Avro Schema简介

    为什么需要schema registry? 首先我们知道: Kafka将字节作为输入并发布 没有数据验证 但是: 如果Producer发送了bad data怎么办? 如果字段被重命名怎么办? 如果数据 ...

  4. JSON数据格式简介

    ---------------siwuxie095                         JSON 简介     JSON:JavaScript 对象表示法(JavaScript Objec ...

  5. 关于JSON的简介及取值以及常见面试题

    关于JSON的简介及取值 JSON(JavaScript Object Notation)一种轻量级的数据交互格式 类似于一种数据封装,可以想象为java中student封装类 JSON的数值可以是数 ...

  6. MySQL5.7 JSON实现简介

    版权声明:本文由吴双桥原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/205 来源:腾云阁 https://www.qclo ...

  7. JSON 的简介与使用

    一.什么是JSON? JSON(javascript object notation)全称是 javascript 对象表示法,是一种数据交换的文本格式,用于读取结构化数据,提出目的是取代繁琐笨重的 ...

  8. 前后端分离构架 与 json ajax简介

    前后端分离 传统开发方式 曾几何时,JSP和Servlet为Java带来了无限风光,一时间大红大紫,但随着互联网的不断发展,这样的开发方式逐渐显露其弊端,在移动互联网炙手可热的今天,应用程序对于后台服 ...

  9. 最强常用开发库总结 - JSON库详解

    最强常用开发库总结 - JSON库详解 JSON应用非常广泛,对于Java常用的JSON库要完全掌握.@pdai JSON简介 JSON是什么 JSON 指的是 JavaScript 对象表示法(Ja ...

  10. JavaScript标准库之——JSON

    JSON 对象包含了两个方法,一是解析 JavaScript Object Notation (JSON),二是将值转换为 JSON.这个对象本身不能被调用或者作为构造函数,除了它的这两个方法属性外 ...

随机推荐

  1. Spring Boot中自动装配机制的原理

    SpringBoot中自动装配机制的原理 1.自动装配,简单来说就是自动把第三方组件的Bean装载到Spring IOC容器里面,不需要开发人员再去写Bean的装配配置, 2.在Spring Boot ...

  2. mpi转以太网连接300PLC实现以太网通信配置方法

    西门子S7300PLC连接MPI-ETH-XD1.0实现以太网通信配置方法 产品简介 兴达易控MPI-ETH-XD1.0用于西门子S7-200/SMART S7-200/S7-300/S7-400/西 ...

  3. linux中的sar命令

    linux中的sar命令 sar命令的安装 [root@localhost test]# yum install sysstat 安装成功! sar命令说明 语法格式 sar [ 选项 ] [ < ...

  4. vue项目使用lodash节流防抖函数问题与解决

    背景 在lodash函数工具库中,防抖_.debounce和节流_.throttle函数在一些频繁触发的事件中比较常用. 防抖函数_.debounce(func, [wait=0], [options ...

  5. 当scroll-view水平滚动,内容溢出时,文本会自动竖向排列问题

    当scroll-view水平滚动,内容溢出时,文本会自动竖向排列 解决方法:thite-space:nowrap:规定段落中的文本不进行换行

  6. Vue之自定义过滤器

    使用Vue.filter('过滤器名称',方法); 1. <!DOCTYPE html> <html lang="en"> <head> < ...

  7. Splay 详细图解 & 轻量级代码实现

    学 LCT 发现有点记不得 Splay 怎么写,又实在不知道这篇博客当时写了些什么东西(分段粘代码?),决定推倒重写. 好像高一学弟也在学平衡树,但相信大家都比樱雪喵强,都能一遍学会!/kel 写在前 ...

  8. 网格布局grid

    起因 昨天面试的时候,出了一道面试题,模拟面试公司的列表的元素宽度伸缩变化,根据屏幕大小的不同,一行上放置最多的元素,元素宽度不固定,间距固定,可换行,靠左对齐,当时猜出来用flexjs监听resiz ...

  9. 会自动写代码的AI大模型来了!仅10秒就写出一个飞机大战游戏!

    一.写在前面 昨天分享了一款可以帮我们写代码的插件CodeGeex,其实能帮我们解决大部分问题,讲道理已经很好了对不对? but,他就是最好的插件吗? 肯定不是,这不又让我又发现了一款可以平替的插件T ...

  10. .Net Core 3.1 服务端配置跨域

    一.在Startup.cs 的 ConfigureServices 配置好跨域策略 原文链接:https://www.jianshu.com/p/534b9a6a6ed5 public void Co ...