• 用.NET代码生成JSON Schema 验证器


    问题

    对于验证复杂JSON数据是否合法的需求,通常的解决方式是标准JSON Schema,.Net下有对应的JSON Schema实现库。应用程序通常需要将标准JSON schema传入实现库,来做后续的数据验证。这里有一种情况,就是如果使用者不太了解标准JSON Schema格式,但又希望能在自己的service中使用其强大的功能,或者适配需要JSON Schema的其他service。

    解决方案

    如果不熟悉标准JSON Schema,可以用Lateapexearlyspeed.Json.Schema 实现库的 fluent schema builder模式 来创建 JSON Schema 验证器。

    这种fluent schema builder用法的接口设计思路是不完全与标准json schema的格式和命名保持一致。标准JSON Schema虽然强大,但大多开发者一般更熟悉“强类型”风格,因此实现库的fluent schema builder在配置时会先“问”用户他们期望哪种JSON token类型,然后在后续链式调用时会基于当前限定的JSON token类型继续“追问”相关的验证需求。通过这种调用方式,开发者会写出更安全的验证代码,利用IDE也会有更友好的使用体验。如下:

        var b = new JsonSchemaBuilder();
        b.ObjectHasProperty("A", b => b.IsJsonString().HasMinLength(5))
        .HasProperty("B", b => b.IsJsonNumber().IsGreaterThan(1).IsLessThan(10))
        .HasProperty("C", b => b.IsJsonArray().HasMinLength(5).HasItems(b =>
        {
            b.NotJsonNull();
        }))
        .HasProperty("D", b => b.Or(
            b => b.IsJsonFalse(),
            b => b.IsJsonNumber().Equal(0),
            b => b.IsJsonObject().HasCustomValidation((JsonElement element) => element.GetProperty("Prop").ValueKind == JsonValueKind.True, 
                jsonElement => $"Cannot pass my custom validation, data is {jsonElement}")
            )
        );
        JsonValidator jsonValidator = b.BuildValidator();
        jsonValidator.Validate(...);
    

    看起来风格是不是很熟悉,即使没接触过JSON Schema,相信也能理解上面的.Net代码。

    目前 fluent schema builder 模式下支持的验证方法:

    • NotJsonNull
    • IsJsonTrue
    • IsJsonFalse
    • IsJsonBoolean
    • IsJsonNull
    • IsJsonString:
      • Equal
      • IsIn
      • HasMaxLength
      • HasMinLength
      • HasPattern
      • HasCustomValidation
      • NotMatch
      • EndsWith
    • StringEqual
    • StringHasPattern
    • IsJsonNumber:
      • Equal
      • IsIn
      • IsGreaterThan
      • IsLessThan
      • NotGreaterThan
      • NotLessThan
      • MultipleOf
      • HasCustomValidation
    • IsJsonArray:
      • SerializationEquivalent
      • HasItems
      • HasLength
      • HasMaxLength
      • HasMinLength
      • HasUniqueItems
      • HasCustomValidation
      • Contains
      • NotContains
      • Equivalent
      • HasCollection
      • Empty
      • NotEmpty
      • Single
    • ArrayHasItems
    • ArrayContains
    • IsJsonObject:
      • SerializationEquivalent
      • HasProperty
      • HasCustomValidation
      • Equivalent
      • HasNoProperty
    • ObjectHasProperty
    • Or

    其中还有HasCustomValidation() overloads 重载方法可以为 JSON树中的指定节点 创建更高级的自定义验证需求。

    不仅想验证JSON数据,还想用 代码Build出来的 Json验证器 来生成 JSON Schema ?

    也可以的

    string standardJsonSchema = jsonValidator.GetStandardJsonSchemaText();
    

    注意:

    为了支持更高级和友好的验证体验,虽然 Lateapexearlyspeed.Json.Schema 实现库在其内部实现时尽可能使用标准JSON Schema keywords, 但一些Build方法会用到“扩展”keywords,因此当你用了那些Build()生成了 JsonValidator 实例后, 将不支持调用 GetStandardJsonSchemaText(),因为扩展keywords无法放回标准JSON Schema且被其他application 所认识,如下:

    var builder = new JsonSchemaBuilder();
    builder.IsJsonNumber().HasCustomValidation((double _) => true, _ => "");
    JsonValidator jsonValidator = builder.BuildValidator();
    
    Assert.Throws(() => jsonValidator.GetStandardJsonSchemaText());
    

    牵扯到扩展keywords的Build方法有:

    • HasCustomValidation(...)
    • HasNoProperty()
    • NotContains()
    • StartsWith()
    • EndsWith()

    总结

    对于验证JSON数据方面的复杂需求,可以用JSON Schema解决。

    对于不希望直接交互JSON Schema格式的service来说,可以用.Net下的 Lateapexearlyspeed.Json.Schema 实现库的 fluent schema builder模式,通过写代码的形式生成JSON验证器。

    对于希望用强类型风格的代码生成JSON Schema的需求,也可以用 Lateapexearlyspeed.Json.Schema 实现库的 fluent schema builder模式。

    Github repo: https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema, 欢迎将使用时发现的问题提到issue。

  • 相关阅读:
    如何使用群晖NAS中FTP服务开启与使用固定地址远程上传下载本地文件?
    quarkus依赖注入之十三:其他重要知识点大串讲(终篇)
    A-Level经济真题每期一练(23)
    Leetcode—283.移动零【简单】
    回溯算法(3)--n皇后问题及回溯法相关习题
    多个Lib module打包合成一个Aar
    【华为OD机试】分苹果
    初阶JavaEE(15)(Cookie 和 Session、理解会话机制 (Session)、实现用户登录网页、上传文件网页、常用的代码片段)
    [异构图-论文阅读]Heterogeneous Graph Transformer
    干了三年的功能测试,让我女朋友跑了,太难受了...
  • 原文地址:https://www.cnblogs.com/dotnet-diagnostic/p/18224293