什么是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. 实现自动扫描工作区npm包并同步cnpm

    省流版: npx cnnc 为避免包名重复,取了2个单词的首尾,cnpm sync 前言 在开发一个多npm包的项目时,时常会一次更新多个包的代码,再批量发布到 npm 镜像源后. 由于国内网络环境的 ...

  2. 《Docker到Kubernetes容器运维实战》简介

    #好书推荐##好书奇遇季#<Docker到Kubernetes容器运维实战>已经出版.本书帮助读者系统掌握Docker与K8s运维技能.   本书内容 本书分两部分系统介绍Docker与K ...

  3. SpringCloud搭建保姆级教程

    一.搭建服务注册与发现中⼼ 使⽤Spring Cloud Netflix 中的 Eureka 搭建服务注册与发现中⼼ 1.创建SpringBoot应用添加依赖 1.spring web 2.eurek ...

  4. LeetCode 周赛上分之旅 #47 前后缀分解结合单调栈的贡献问题

    ️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问. 学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越 ...

  5. 前端三件套系例之JS——JavaScript内置方法

    文章目录 1.Number 1-1 属性 1-2 方法 2.String 2-1 属性 2-2 方法 2-3 代码 3Array 3-1 创建数组 3-2 数组特点 3-3 数组的遍历(迭代) 34 ...

  6. 高效数据传输:Java通过绑定快速将数据导出至Excel

    摘要:本文由葡萄城技术团队于博客园原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 把数据导出至 Excel 是很常见的需求,而数据的持久化 ...

  7. Python - 打断点以及如何查看

    1.鼠标左键单击代码跟行号中间的地方会出现一个红点,这个就是断点. 2.点击Debug按钮,进入调试模式. 3.当代码运行到断点之前,所有关于变量的代码,都会出现运行的结果. 4.点击Step Int ...

  8. Java虚拟机(JVM):第三幕:自动内存管理 - 垃圾收集器与内存分配策略

    前言:Java与C++之间有一堵高墙,主要是有内存动态分配和垃圾收集技术组成的.墙外的人想要进来,墙内的人想要出去. 一.概述 每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的.内存的分配和 ...

  9. 使用 Alacritty 替代 Gnome-Terminal 解决 Ubuntu 中终端的行间距问题

    我之前发了一篇随笔新版 Ubuntu 中 gnome-terminal 可恶的行间距问题逼我退回了 Ubuntu 20.04,描述了新版 Ubuntu 中终端的行间距问题.评论中给出了一个解决办法,那 ...

  10. 虹科喜报 | 虹科技术工程师【国内首批】拿下Redis认证开发者证书!

    要说虹科数据库技术工程师有多强悍,认证考试2022年12月上线,次年2月就以全国首批速度强势通过考试,并于两周后正式收到[Redis认证开发人员]证书! 虹科小云忍不住浅浅炫耀一下: 或许大家对Red ...