首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

用了json这么久我猜你一定不知道json schema是啥

  • 25-04-22 01:01
  • 4122
  • 13973
juejin.cn

大家好,这里是小奏,觉得文章不错可以关注公众号小奏技术

什么是 json schema

json schema 是一种用于描述 json 数据结构的语言,它可以用来定义 json 数据的类型、格式、约束等信息。

json schema 本身是一个也是json数据

主要用途

  • 数据校验
  • 数据结构定义
  • API文档生成
  • 代码生成

github地址

  • json-schema-spec

文档

  • json-schema-doc
  • json-schema-中文

java相关sdk选型

json schema推荐了各个语言相关sdk

  • 链接

这里我们主要看看java相关的sdk有哪些

简单对上面的一些进行调研分析

项目地址start数量项目活跃情况备注
github.com/everit-org/…861基本不维护这个是最早的json-schema的java实现,推荐使用json-sKema
github.com/erosb/json-…49活跃与json-schema是同一个作者,不同的是这个是最新的
github.com/networknt/j…848活跃jackson官方使用的是这个库,目前主流的json序列化库也是使用的这个库,所以推荐使用这个库

这里推荐是使用json-schema-validator

json-schema-validator也给了一份详细的对比文档

总体功能对比(越高越好)

整体可选功能(越高越好)

性能对比(越低越好)

更多对比参考文档 www.creekservice.org/json-schema…

json schema数据校验格式

这里我们主要探讨的是json schema如何对json数据如何进行数据校验

语法

中文文档其实说的已经很全面了,我们这里就主要对几种常用的对象类型的数据格式校验进行说明

必须包含某些属性

json
代码解读
复制代码
{ "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "address": { "type": "string" }, "telephone": { "type": "string" } }, "required": ["name", "email"] }

主要使用required关键字

这里代表json中必须包含name和email属性

json
代码解读
复制代码
// OK { "name": "William Shakespeare", "email": "[email protected]" } // OK,提供额外的属性是可以的,即使是架构中没有定义的属性: { "name": "William Shakespeare", "email": "[email protected]", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England", "authorship": "in question" } // not OK,缺少必需的“email”属性会使 JSON 文档无效 { "name": "William Shakespeare", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England", } // not OK,在 JSON 中,具有值的属性null不等同于不存在的属性。这失败,因为null不是“字符串”类型,而是“空”类型 { "name": "William Shakespeare", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England", "email": null }

不能包含额外属性

json
代码解读
复制代码
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": false }

主要是通过additionalProperties控制

json
代码解读
复制代码
// OK { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // not OK,额外属性“direction”使对象无效 { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }

当然,也可以使用非布尔类型进行更灵活的限制 比如 所有额外属性必须是字符串

json
代码解读
复制代码
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": { "type": "string" } }
json
代码解读
复制代码
// OK { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // OK,这是有效的,因为附加属性的值是一个字符串 { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" } // not OK,这是无效的,因为附加属性的值不是字符串: { "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "office_number": 201 }

对所有属性进行正则校验

我们也可以通过正则对所有属性进行更灵活的正则匹配校验

json
代码解读
复制代码
{ "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" } }
json
代码解读
复制代码
// OK { "_a_proper_token_001": "value" } // not OK { "001 invalid": "value" }

属性数量限制

我们可以通过minProperties和maxProperties来限制属性的数量

json
代码解读
复制代码
{ "type": "object", "minProperties": 2, "maxProperties": 3 }
json
代码解读
复制代码
{} // not OK { "a": 0 } // not OK { "a": 0, "b": 1 } // OK { "a": 0, "b": 1, "c": 2 } // OK { "a": 0, "b": 1, "c": 2, "d": 3 } // not OK

java sdk初体验

这里我们以json-sKema和json-schema-validator进行举例

  • jdk 17

json-sKema

  1. 引入依赖
xml
代码解读
复制代码
<dependency> <groupId>com.github.erosbgroupId> <artifactId>json-sKemaartifactId> <version>0.18.0version> dependency> <dependency> <groupId>org.jetbrains.kotlingroupId> <artifactId>kotlin-stdlibartifactId> <version>1.8.0version> dependency>
  1. 代码使用
java
代码解读
复制代码
public class JsonsKemaTest { private static final Validator validator; static { JsonValue schemaJson = new JsonParser(""" { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "age": { "type": "number", "minimum": 0 }, "name": { "type": "string" }, "email": { "type": "string", "format": "email" } } } """).parse(); Schema schema = new SchemaLoader(schemaJson).load(); validator = Validator.create(schema, new ValidatorConfig(FormatValidationPolicy.ALWAYS)); } @Test public void testJsonSchemaFailure() { JsonValue instance = new JsonParser(""" { "age": -5, "name": null, "email": "invalid" } """).parse(); ValidationFailure failure = validator.validate(instance); if (Objects.nonNull(failure)) { failure.getCauses().forEach(System.out::println); } } @Test public void testJsonSchemaSuccess() { JsonValue success = new JsonParser(""" { "age": 3, "name": "xiaozou", "email": "[email protected]" } """).parse(); ValidationFailure validateSuccess = validator.validate(success); if (Objects.isNull(validateSuccess)) { System.out.println(" validate json success"); } } }

校验失败运行结果

json-sKema

  1. 引入依赖
xml
代码解读
复制代码
<dependency> <groupId>com.networkntgroupId> <artifactId>json-schema-validatorartifactId> <version>1.5.2version> dependency>
  1. 代码使用
java
代码解读
复制代码
class JsonSchemaDemoTest { private static final JsonSchema jsonSchema; static { String schemaData = """ { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "age": { "type": "number", "minimum": 0 }, "name": { "type": "string" }, "email": { "type": "string", "format": "email" } } } """; JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012, builder -> builder.jsonNodeReader(JsonNodeReader.builder().locationAware().build())); SchemaValidatorsConfig config = SchemaValidatorsConfig.builder().build(); jsonSchema = factory.getSchema(schemaData, InputFormat.JSON, config); } @Test public void testValidationSuccess() { String input = """ { "age": 3, "name": "xiaozou", "email": "[email protected]" } """; Set assertions = jsonSchema.validate(input, InputFormat.JSON, executionContext -> { // By default since Draft 2019-09 the format keyword only generates annotations and not assertions executionContext.getExecutionConfig().setFormatAssertionsEnabled(true); }); System.out.println(assertions); } @Test public void testJsonSchemaFailure() { String input = """ { "age": -5, "name": null, "email": "invalid" } """; Set assertions = jsonSchema.validate(input, InputFormat.JSON, executionContext -> { // By default since Draft 2019-09 the format keyword only generates annotations and not assertions executionContext.getExecutionConfig().setFormatAssertionsEnabled(true); }); System.out.println(assertions); } }

校验失败运行结果

[/age: 最小值必须为 0, /name: 已找到 null,必须是 string, /email: 与 email 模式不匹配必须是有效的 RFC 5321 邮箱]

可以看到相比于json-sKema,json-schema-validator的校验结果使用起来更方便、简洁

总结

总的来说如果需要进行json数据校验,推荐使用json-schema-validator,它的校验结果更加简洁,使用起来更加方便

在官方的对比文档中也可以看出来json-schema-validator的功能更加全面,性能也更好,可扩展性也是非常强的

同时json-schema-validator也是目前主流的json序列化库使用的校验库

注:本文转载自juejin.cn的小奏技术的文章"https://juejin.cn/post/7432207211370201140"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top