Json Schema简介和Json Schema的.net实现库 LateApexEarlySpeed.Json.Schema

这篇具有很好参考价值的文章主要介绍了Json Schema简介和Json Schema的.net实现库 LateApexEarlySpeed.Json.Schema。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是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数据。
Json Schema语法的学习见官方介绍。

比如下面的一个简单例子,用.net下的Json Schema实现库library 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实现库library,基于截止到2023年12月为止最新版的Json schema - draft 2020.12。
Json Schema验证功能经过了official json schema test-suite for draft 2020.12的测试。(部分排除的用例见下面的已知限制章节)

主要特点:

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

一些性能测试结果 (下面的测试比较都是在同样的使用方式下进行,见 性能建议 ):
12th Gen Intel Core i7-12800H, 1 CPU, 20 logical and 14 physical cores

[Host] : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2

DefaultJob : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2

有效数据用例:

Method Mean Error StdDev Gen0 Gen1 Allocated
ValidateByPopularSTJBasedValidator 29.80 us 0.584 us 0.573 us 4.4556 0.2441 55.1 KB
ValidateByThisValidator 15.99 us 0.305 us 0.300 us 1.9531 - 24.2 KB

无效数据用例:

Method Mean Error StdDev Median Gen0 Gen1 Allocated
ValidateByPopularSTJBasedValidator 65.04 us 2.530 us 7.341 us 66.87 us 4.5776 0.1221 56.42 KB
ValidateByThisValidator 15.47 us 1.160 us 3.421 us 17.14 us 1.4954 - 18.45 KB

Note: "STJ"是"System.Text.Json"的缩写,这个是.net sdk里默认带的json基础包, LateApexEarlySpeed.Json.Schema这个库也是基于这个STJ编写的。

基准Schema:

{
  "$id": "http://main",
  "type": "object",

  "additionalProperties": false,
  "patternProperties": {
    "propB*lean": {
      "type": "boolean"
    }
  },
  "dependentRequired": {
    "propNull": [ "propBoolean", "propArray" ]
  },
  "dependentSchemas": {
    "propNull": {
      "type": "object"
    }
  },
  "propertyNames": true,
  "required": [ "propNull", "propBoolean" ],
  "maxProperties": 100,
  "minProperties": 0,
  "properties": {
    "propNull": {
      "type": "null"
    },
    "propBoolean": {
      "type": "boolean",
      "allOf": [
        true,
        { "type": "boolean" }
      ]
    },
    "propArray": {
      "type": "array",
      "anyOf": [ false, true ],
      "contains": { "type": "integer" },
      "maxContains": 100,
      "minContains": 2,
      "maxItems": 100,
      "minItems": 1,
      "prefixItems": [
        { "type": "integer" }
      ],
      "items": { "type": "integer" },
      "uniqueItems": true
    },
    "propNumber": {
      "type": "number",
      "if": {
        "const": 1.5
      },
      "then": true,
      "else": true,
      "enum": [ 1.5, 0, 1 ]
    },
    "propString": {
      "type": "string",
      "maxLength": 100,
      "minLength": 0,
      "not": false,
      "pattern": "abcde"
    },
    "propInteger": {
      "$ref": "#/$defs/typeIsInteger",
      "exclusiveMaximum": 100,
      "exclusiveMinimum": 0,
      "maximum": 100,
      "minimum": 0,
      "multipleOf": 0.5,
      "oneOf": [ true, false ]
    }
  },
  "$defs": {
    "typeIsInteger": { "$ref": "http://inside#/$defs/typeIsInteger" },
    "toTestAnchor": {
      "$anchor": "test-anchor"
    },
    "toTestAnotherResourceRef": {
      "$id": "http://inside",
      "$defs": {
        "typeIsInteger": { "type": "integer" }
      }
    }
  }
}

有效基准数据:

{
  "propNull": null,
  "propBoolean": true,
  "propArray": [ 1, 2, 3, 4, 5 ],
  "propNumber": 1.5,
  "propString": "abcde",
  "propInteger": 1
}

无效基准数据:

{
  "propNull": null,
  "propBoolean": true,
  "propArray": [ 1, 2, 3, 4, 4 ], // Two '4', duplicated
  "propNumber": 1.5,
  "propString": "abcde",
  "propInteger": 1
}

该实现库(implementation library)之后可能会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支持

目前library支持如下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 .

限制

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

问题报告

欢迎把使用过程中遇到的问题和希望增加的功能发到github repo issue中文章来源地址https://www.toymoban.com/news/detail-760675.html

More doc is to be written

到了这里,关于Json Schema简介和Json Schema的.net实现库 LateApexEarlySpeed.Json.Schema的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Jetpack】使用 Room Migration 升级数据库并导出 Schema 文件 ( Schema 文件简介 | 生成 Schema 文件配置 | 生成 Schema 文件过程 )

    使用 Room Migration 升级数据库 , 需要根据当前数据库版本和目标版本编写一系列 Migration 迁移类 , 并生成一个升级的 Schema 文件 , 该文件是 json 格式的文件 , 其中包含如下内容 : 版本信息 : 包括 当前版本 和 目标版本 ; 创建表语句 : 包括 新增的表的 定义 和 字段信息 ; 删除表语

    2024年02月09日
    浏览(36)
  • 解决./composer.json" does not match the expected JSON schema

    如果执行composer install的时候报错 这是因为name里的格式不符合要求,需要 有/   ,并且不能有大写,仔细检查下正则那句话 无语!

    2024年02月16日
    浏览(48)
  • 数据库模式(schema)是什么?

    在数据库的术语中,模式(schema)是一个逻辑概念,用于组织数据库中的对象。模式中的对象通常包括表、索引、数据类型、序列、视图、存储过程、主键、外键等等。 模式可以为数据库对象提供逻辑隔离功能,不用应用程序可以使用各自的模式,实现安全的访问权限控制。

    2024年02月06日
    浏览(41)
  • vue3-json-schema-form中StringField.vue报错 `<script setup>` cannot contain ES module exports vue/no-e

    vue3-json-schema-form课程中StringField.vue照着打报错 原代码如下: 修改后代码如下: type.ts文件代码片段如下: 主要问题就是说script标签中加上setup,代码块中不能再出现export default,将该部分代码 修改为:

    2024年02月11日
    浏览(25)
  • VB.net:VB.net编程语言学习之ADO.net基本名称空间与类的简介、案例应用(实现与SQL数据库编程案例)之详细攻略

    VB.net:VB.net编程语言学习之ADO.net基本名称空间与类的简介、案例应用(实现与SQL数据库编程案例)之详细攻略 目录 ADO.net基本名称空间与类 1、ADO.net六个基础名称空间 2、ADO.net类

    2024年02月06日
    浏览(32)
  • JSON简介

    JSON:(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易

    2024年02月11日
    浏览(19)
  • JSON简介与使用

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于 JavaScript 语言的标准语法,但独立于语言和平台,被广泛应用于多种编程环境间的数据交互。JSON的设计理念是既方便人类阅读又利于机器解析,它通过简洁的文本形式来表达复杂的数据结构。 JSON的基本结构与

    2024年02月22日
    浏览(24)
  • JWT(Json Web Token)简介

    一般的Token认证流程是这样的:         1. 用户输入用户名和密码,发送给服务器。          2. 服务器验证用户名和密码,正确的话就返回一个签名过的token(token 可以认为就是个长长的字符串),浏览器客户端拿到这个token。          3. 后续每次请求中,浏览器

    2023年04月08日
    浏览(24)
  • Jmeter常用断言之JSON断言简介

    JSON断言可以对服务器返回的JSON文档进行验证。 JSON断言有两种使用模式: 1.根据JSONPath能否在JSON文档中找到路径; 2.根据JSONPath提取值并对值进行验证。 结果判定 :若文档格式为非JSON则断言失败;找不到路径断言失败;提取值与预期值不一致断言失败。 根据需要可在【测试

    2024年02月05日
    浏览(24)
  • Newtonsoft.Json/Json.NET忽略序列化时的意外错误

    在.NET中Newtonsoft.Json(Json.NET)是我们常用来进行Json序列化与反序列化的库。 而在使用中常会遇到反序列化Json时,遇到不规则的Json数据解构而抛出异常。 Newtonsoft.Json 支持序列化和反序列化过程中的错误处理。 允许您捕获错误并选择是处理它并继续序列化,还是让错误冒泡并抛

    2024年03月21日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包