如何删除两个相似的 JSON 模式?
How can I de-duplicate two similar JSON Schemas?
我在模式定义中有以下服务对象:
"services": {
"type": "object"
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service names must be non-numeric"
}
"patternProperties": {
"^[A-Za-z_]*$": {
"type": "object"
"properties": {
"source": {
"type": ["string", "object"]
},
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"errorMessage": "invalid cpu value
},
"memory": {
"type": "number",
"errorMessage": "invalid memory value
},
"overrides": { "$ref": "#/definitions/overrides" },
"allOf": [...]
}
}
}
在单独的定义中,我维护了以下覆盖对象:
"overrides": {
"type": "object",
"propertyNames": {
"pattern": "^(dev|int|trn|qa|stag|prod)?$",
"errorMessage": "override stage name must be approved environment (dev, int, trn, qa, stag, prod)"
},
"patternProperties": {
"^(dev|int|trn|qa|stag|prod)?$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "override property name must be non-numeric"
},
"properties": {
"$ref": "..."
},
"allOf": [...]
}
}
}
对于某些上下文,这是一个配置文件,其中使用端口、源、cpu、内存和其他选项定义服务对象。每个服务都可以有一个覆盖对象,可用于替换每个环境的服务对象属性...例如
{
"services": {
"main": {
"source": "https://github.com/foo,
"port": 3000,
"cpu": 256,
"memory": 1,
"overrides": {
"prod": {
"port": 8443
}
}
}
}
}
我的目标是对此进行优化,这样我就不必维护两个相同的模式。现在,服务定义中存在的每个 属性 基本上都被复制为覆盖对象的 属性。我还维护单独的“allOf”验证,因为服务对象属性是必需的,但覆盖对象属性都是可选的。
是否可以利用 $ref 功能从覆盖定义中指向服务定义的属性?此外,是否有可能完全摆脱覆盖模式并重用服务模式,或者它们的模式 patternProperties 中的差异是否阻止了这种情况?
感谢任何可能帮助我克服困难的指导。
为简洁起见,完整架构减去了 allOf 块:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"services": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service names must be non-numeric"
},
"patternProperties": {
"^[A-Za-z_]*$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service property names must be non-numeric"
},
"properties": {
"source": {
"type": ["string", "object"]
},
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
"environment": {
"type": "object",
"errorMessage": "invalid environment variables defined - must be an object"
},
"overrides": { "$ref": "#/definitions/overrides" }
},
"required": ["source", "port", "cpu", "memory", "min_instances"],
"errorMessage": {
"required": {
"source": "missing service source",
"port": "missing service port",
"cpu": "missing service cpu",
"memory": "missing service memory",
"min_instances": "missing minimum required service instances"
},
"type": "service must have at least one defined property",
"additionalProperties": "invalid property found in service definition"
},
"allOf": [...],
"additionalProperties": false
}
},
"errorMessage": { "type": "must have at least one defined service" }
},
"overrides": {
"type": "object",
"propertyNames": {
"pattern": "^(dev|int|trn|qa|stag|prod)?$",
"errorMessage": "override stage name must be approved environment (dev, int, trn, qa, stag, prod)"
},
"patternProperties": {
"^(dev|int|trn|qa|stag|prod)?$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "override property name must be non-numeric"
},
"properties": {
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
"environment": {
"type": "object",
"errorMessage": "invalid environment variables defined - must be an object"
}
},
"errorMessage": {
"type": "environment must have at least one defined override",
"additionalProperties": "invalid property found in override definition"
},
"allOf": [...],
"additionalProperties": false
}
},
"errorMessage": { "type": "overrides must have at least one defined environment" }
}
},
"type": "object",
"properties": {
"name": {
"type": "string",
"errorMessage": "app name should be string"
},
"account": {
"type": "string",
"errorMessage": "invalid account value"
},
"id": {
"type": "string",
"errorMessage": "invalid id tag value"
},
"services": {
"$ref": "#/definitions/services"
},
"stages": {
"type": "array",
"errorMessage": "invalid stages option - must be an array"
}
},
"required": ["name", "account", "id", "services"],
"errorMessage": {
"required": {
"name": "missing app name",
"account": "missing designated account",
"id": "missing designated id tag",
"services": "no services are defined"
}
}
}
因为您已经为一些不同的属性添加了字段,所以您不能删除所有的重复项。 errorMessage
不是 JSON 架构规范的一部分,因此它的使用仅限于您正在使用的库。
您可以删除一些属性,并且您已经使用了引用 ($ref
)。
您可以将 memory
组件移动到它自己的定义...
...
"definitions": {
"componentMemory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
...
然后在两个子模式位置引用它...
...
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"$ref": "#/definitions/services"
},
...
如果您不太关心错误消息,则可以进一步删除重复数据,但我猜您确实关心它们。
因此,只要子模式相同,就可以删除重复项。
properties
对象的值是子模式。
我在模式定义中有以下服务对象:
"services": {
"type": "object"
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service names must be non-numeric"
}
"patternProperties": {
"^[A-Za-z_]*$": {
"type": "object"
"properties": {
"source": {
"type": ["string", "object"]
},
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"errorMessage": "invalid cpu value
},
"memory": {
"type": "number",
"errorMessage": "invalid memory value
},
"overrides": { "$ref": "#/definitions/overrides" },
"allOf": [...]
}
}
}
在单独的定义中,我维护了以下覆盖对象:
"overrides": {
"type": "object",
"propertyNames": {
"pattern": "^(dev|int|trn|qa|stag|prod)?$",
"errorMessage": "override stage name must be approved environment (dev, int, trn, qa, stag, prod)"
},
"patternProperties": {
"^(dev|int|trn|qa|stag|prod)?$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "override property name must be non-numeric"
},
"properties": {
"$ref": "..."
},
"allOf": [...]
}
}
}
对于某些上下文,这是一个配置文件,其中使用端口、源、cpu、内存和其他选项定义服务对象。每个服务都可以有一个覆盖对象,可用于替换每个环境的服务对象属性...例如
{
"services": {
"main": {
"source": "https://github.com/foo,
"port": 3000,
"cpu": 256,
"memory": 1,
"overrides": {
"prod": {
"port": 8443
}
}
}
}
}
我的目标是对此进行优化,这样我就不必维护两个相同的模式。现在,服务定义中存在的每个 属性 基本上都被复制为覆盖对象的 属性。我还维护单独的“allOf”验证,因为服务对象属性是必需的,但覆盖对象属性都是可选的。
是否可以利用 $ref 功能从覆盖定义中指向服务定义的属性?此外,是否有可能完全摆脱覆盖模式并重用服务模式,或者它们的模式 patternProperties 中的差异是否阻止了这种情况?
感谢任何可能帮助我克服困难的指导。
为简洁起见,完整架构减去了 allOf 块:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"services": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service names must be non-numeric"
},
"patternProperties": {
"^[A-Za-z_]*$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "service property names must be non-numeric"
},
"properties": {
"source": {
"type": ["string", "object"]
},
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
"environment": {
"type": "object",
"errorMessage": "invalid environment variables defined - must be an object"
},
"overrides": { "$ref": "#/definitions/overrides" }
},
"required": ["source", "port", "cpu", "memory", "min_instances"],
"errorMessage": {
"required": {
"source": "missing service source",
"port": "missing service port",
"cpu": "missing service cpu",
"memory": "missing service memory",
"min_instances": "missing minimum required service instances"
},
"type": "service must have at least one defined property",
"additionalProperties": "invalid property found in service definition"
},
"allOf": [...],
"additionalProperties": false
}
},
"errorMessage": { "type": "must have at least one defined service" }
},
"overrides": {
"type": "object",
"propertyNames": {
"pattern": "^(dev|int|trn|qa|stag|prod)?$",
"errorMessage": "override stage name must be approved environment (dev, int, trn, qa, stag, prod)"
},
"patternProperties": {
"^(dev|int|trn|qa|stag|prod)?$": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_]*$",
"errorMessage": "override property name must be non-numeric"
},
"properties": {
"port": {
"type": "number",
"errorMessage": "invalid port value"
},
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
"environment": {
"type": "object",
"errorMessage": "invalid environment variables defined - must be an object"
}
},
"errorMessage": {
"type": "environment must have at least one defined override",
"additionalProperties": "invalid property found in override definition"
},
"allOf": [...],
"additionalProperties": false
}
},
"errorMessage": { "type": "overrides must have at least one defined environment" }
}
},
"type": "object",
"properties": {
"name": {
"type": "string",
"errorMessage": "app name should be string"
},
"account": {
"type": "string",
"errorMessage": "invalid account value"
},
"id": {
"type": "string",
"errorMessage": "invalid id tag value"
},
"services": {
"$ref": "#/definitions/services"
},
"stages": {
"type": "array",
"errorMessage": "invalid stages option - must be an array"
}
},
"required": ["name", "account", "id", "services"],
"errorMessage": {
"required": {
"name": "missing app name",
"account": "missing designated account",
"id": "missing designated id tag",
"services": "no services are defined"
}
}
}
因为您已经为一些不同的属性添加了字段,所以您不能删除所有的重复项。 errorMessage
不是 JSON 架构规范的一部分,因此它的使用仅限于您正在使用的库。
您可以删除一些属性,并且您已经使用了引用 ($ref
)。
您可以将 memory
组件移动到它自己的定义...
...
"definitions": {
"componentMemory": {
"type": "number",
"enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30],
"errorMessage": "memory value should be 0.5 - 30"
},
...
然后在两个子模式位置引用它...
...
"cpu": {
"type": "number",
"enum": [256, 512, 1024, 2048, 4096],
"errorMessage": "invalid cpu value - should be one of the following: 256, 512, 1024, 2048, 4096"
},
"memory": {
"$ref": "#/definitions/services"
},
...
如果您不太关心错误消息,则可以进一步删除重复数据,但我猜您确实关心它们。
因此,只要子模式相同,就可以删除重复项。
properties
对象的值是子模式。