如何验证 child 属性 在 object 中的所有 children 中仅设置一次
How to validate that child property is set only once amongst all children in object
我正在尝试验证以下内容 JSON
{
"domain": "example.com",
"docker": {
"services": {
"app": {
"image": "nginxdemos/hello:latest",
"expose_port": 80,
"volumes": [
"./:/test"
]
},
"db": {
"image": "mariadb:10.5"
}
}
}
}
我想确保 services
children 里面的 expose_port
只能定义一次。因此,将 "expose_port": 1234
添加到 "db" 应该会使 JSON.
无效
这是我目前的架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://saitho.me/project-configuration.schema.json",
"title": "Project Configuration",
"description": "Project configuration file",
"type": "object",
"definitions": {
"docker-service": {
"properties": {
"image": {
"description": "Name of Docker image",
"type": "string"
},
"volumes": {
"description": "Docker volumes to be mounted",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
}
},
"required": [ "image" ]
}
},
"properties": {
"domain": {
"description": "The domain from which the app can be reached",
"type": "string"
},
"docker": {
"description": "Configuration for Docker containers that will be deployed",
"type": "object",
"properties": {
"services": {
"description": "List of Docker services to be started",
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/definitions/docker-service",
"oneOf": [
{
"properties": {
"expose_port": {
"description": "Port that receives web traffic (e.g. 80, 3000, 8080 for most applications). Only one in this file!",
"type": "integer"
}
}
}
],
"type": "object"
}
},
"additionalProperties": false
}
},
"required": [ "services" ]
}
},
"required": [ "domain" ]
}
到目前为止,我已经尝试将 allOf 和 oneOf 结合使用,但这似乎只适用于当前 child 而不是同时查看兄弟姐妹。有谁知道我的问题的解决方案? :)
谢谢!
如果您有一组特定的服务(例如,暴露的端口只会在 "app" 或 "db" 上),您可以使用 "oneOf" 来测试那个两者中的一个有 属性(或两者都没有,作为第三次测试)。
如果您有任意一组服务,那么您将不再执行 "structural" 验证,而是进入业务逻辑领域。在这种情况下,每个值都可能取决于所有其他值的值。单独使用 JSON 架构验证无法验证这一点,请参阅页面 Scope of JSON Schema Validation 了解更多信息。
但是,您可以对 JSON 文档进行布局以匹配您要完成的任务。如果有一个 属性 只能定义一次,那么将 属性 定义分解到一个只能定义一次的地方:
{
"domain": "example.com",
"docker": {
"services": {
"app": {
"image": "nginxdemos/hello:latest",
"volumes": [
"./:/test"
]
},
"db": {
"image": "mariadb:10.5"
}
},
"expose_service": "app",
"expose_port": 80
}
}
我正在尝试验证以下内容 JSON
{
"domain": "example.com",
"docker": {
"services": {
"app": {
"image": "nginxdemos/hello:latest",
"expose_port": 80,
"volumes": [
"./:/test"
]
},
"db": {
"image": "mariadb:10.5"
}
}
}
}
我想确保 services
children 里面的 expose_port
只能定义一次。因此,将 "expose_port": 1234
添加到 "db" 应该会使 JSON.
这是我目前的架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://saitho.me/project-configuration.schema.json",
"title": "Project Configuration",
"description": "Project configuration file",
"type": "object",
"definitions": {
"docker-service": {
"properties": {
"image": {
"description": "Name of Docker image",
"type": "string"
},
"volumes": {
"description": "Docker volumes to be mounted",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
}
},
"required": [ "image" ]
}
},
"properties": {
"domain": {
"description": "The domain from which the app can be reached",
"type": "string"
},
"docker": {
"description": "Configuration for Docker containers that will be deployed",
"type": "object",
"properties": {
"services": {
"description": "List of Docker services to be started",
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/definitions/docker-service",
"oneOf": [
{
"properties": {
"expose_port": {
"description": "Port that receives web traffic (e.g. 80, 3000, 8080 for most applications). Only one in this file!",
"type": "integer"
}
}
}
],
"type": "object"
}
},
"additionalProperties": false
}
},
"required": [ "services" ]
}
},
"required": [ "domain" ]
}
到目前为止,我已经尝试将 allOf 和 oneOf 结合使用,但这似乎只适用于当前 child 而不是同时查看兄弟姐妹。有谁知道我的问题的解决方案? :)
谢谢!
如果您有一组特定的服务(例如,暴露的端口只会在 "app" 或 "db" 上),您可以使用 "oneOf" 来测试那个两者中的一个有 属性(或两者都没有,作为第三次测试)。
如果您有任意一组服务,那么您将不再执行 "structural" 验证,而是进入业务逻辑领域。在这种情况下,每个值都可能取决于所有其他值的值。单独使用 JSON 架构验证无法验证这一点,请参阅页面 Scope of JSON Schema Validation 了解更多信息。
但是,您可以对 JSON 文档进行布局以匹配您要完成的任务。如果有一个 属性 只能定义一次,那么将 属性 定义分解到一个只能定义一次的地方:
{
"domain": "example.com",
"docker": {
"services": {
"app": {
"image": "nginxdemos/hello:latest",
"volumes": [
"./:/test"
]
},
"db": {
"image": "mariadb:10.5"
}
},
"expose_service": "app",
"expose_port": 80
}
}