问题描述
如何在JSON模式中子类化?
首先,我将自己限于07草案,因为这是我所能找到的实现方式。
中进行了描述https://json-schema.org/understanding-json-schema/structuring.html#extending
但这在'additionalProperties'方面效果不佳:false?
为什么要打扰 另外的属性”:否?
没有它-几乎所有随机垃圾输入json将被视为有效,因为所有 “错误”(错误的json)将仅被视为“ additionalProperties”。
重新设置https://json-schema.org/understanding-json-schema/structuring.html#extending
此问题-是不适用于“ additionalProperties”(因为 仅适用于其他属性的不清楚但很不幸的定义 到本地定义的(在该子模式中)属性,因此一个或另一个模式将无法通过验证。
替代方法:
-
元语言/解释器位于JSONSchema之上 (例如https://github.com/mokkabonna/json-schema-merge-allof)
这不是一个好选择,因为scehma只能从javascript中使用(或 元处理器的语言)。而且不容易与其他工具互操作
-
https://github.com/java-json-tools/json-schema-validator/wiki/v5%3A-merge
-
我将提出的另一种解决方案/答案
解决方法
这不是一个很好的答案。但是,直到改进JSONSchema的定义(或者有人提供更好的答案)之前,这就是我提出的可行的方法。
基本上,您为每种类型定义两个副本,第一个具有所有详细信息,但没有其他属性:false标志。然后第二个,参考第一个,但设置了“ additionalProperties:false”。
您可以将第一个视为“抽象类”,将第二个视为“具体类”。
然后,将https://json-schema.org/understanding-json-schema/structuring.html#extending方法用于“子类”,但引用ABSTRACT类,然后添加“ additionalProperties:false”。值得一提的是,要使这项工作有效,您还必须重复所有继承的属性(但不必包括它们的类型信息-仅包括它们的名称),这是由于JSONSchema草案7似乎是如何解释AdditionalProperties的不幸选择。
基于https://json-schema.org/understanding-json-schema/structuring.html#extending的示例应有帮助:
https://www.jsonschemavalidator.net/s/3fhU3O1X
(在其他站点的情况下在此处复制 / link并非永久/可靠)
{
"$schema": "http://json-schema.org/draft-07/schema#","$id": "https://TEST","definitions": {
"interface-address": {
"type": "object","properties": {
"street_address": {
"type": "string"
},"city": {
"type": "string"
},"state": {
"type": "string"
}
},"required": ["street_address","city","state"]
},"concrete-address": {
"allOf": [
{
"$ref": "#/definitions/interface-address"
}
],"properties": {
"street_address": {},"city": {},"state": {}
},"additionalProperties": false
},"in-another-file-subclass-address": {
"allOf": [
{
"$ref": "#/definitions/interface-address"
}
],"additionalProperties": false,"state": {},"type": {
"enum": ["residential","business"]
}
},"required": ["type"]
},"test-of-address-schemas": {
"type": "object","properties": {
"interface-address-allows-bad-fields": {
"$ref": "#/definitions/interface-address"
},"use-concrete-address-to-only-admit-legit-addresses-without-extra-crap": {
"$ref": "#/definitions/concrete-address"
},"still-can-subclass-using-interface-not-concrete": {
"$ref": "#/definitions/in-another-file-subclass-address"
}
}
}
},"anyOf": [
{
"$ref": "#/definitions/test-of-address-schemas"
}
]
}
和示例文档:
{
"interface-address-allows-bad-fields":{
"street_address":"s","city":"s","state":"s","allow-bad-fields-this-is-why-we-need-additionalProperties":"s"
},"use-concrete-address-to-only-admit-legit-addresses-without-extra-crap":{
"street_address":"s","state":"s"
},"still-can-subclass-using-interface-not-concrete":{
"street_address":"s","type":"business"
}
}
,
如何在JSON-Schema中子类化?
您不需要,因为JSON架构不是面向对象的,架构也不是类。 JSON Schema专为验证而设计。模式是约束的集合。
但是,无论如何,让我们从面向对象的角度来看它。
关于继承的构成
首先要注意的是,JSON Schema不支持继承的模拟。您可能熟悉旧的面向对象的知识,即“继承之上的组成”。 Go语言选择完全不支持继承,因此JSON Schema与这种方法紧密结合。如果仅使用合成构建系统,则"additionalProperties": false
不会有任何问题。
多态
让我们说,关于构图的思考太陌生了(花时间学习不同的思维),或者您无法控制类型的设计。无论出于何种原因,都需要使用继承为数据建模,可以使用您熟悉的allOf
模式。 allOf
模式与继承并不完全相同,但是它是您将要获得的最接近的模式。
您已经注意到,"additionalProperties": false
与allOf
模式一起造成了严重破坏。那么,为什么要忽略这个呢? OO答案是多态。假设您有一个“人”类型和一个扩展“人”的“学生”类型。如果您有一个学生,则应该能够将其传递给接受人的方法。不管Student具有Person所没有的一些属性,当它用作Person时,多余的属性都将被忽略。如果您使用"additionalProperties": false
,则您的类型不能是多态的。
这些都不是您要的那种解决方案,但是希望它给您一个不同的角度来考虑以其他方式解决问题的替代方法,这对于JSON Schema来说更常见。