JSON 架构 - 动态所需属性

JSON Schema - Dynamic required properties

我有一个模式来验证传入的 JSON,

JSON 架构

{
    'title': 'storage schema',
    'description': 'storage schema',
    'type': 'object',
    'properties':{
        'title': {
            'title':'storage Name',
            'type': 'string',
            'minLength': 1,
            'maxLength': 255
        },
        'storageType': {
            'title': 'storage Type',
            'enum' : ['DVD', 'HDD', 'Network', 'Internet']
        },
        'minCapacity': {
            'title': 'Minimum Storage Capacity',
            'type': 'number'
        },
        'maxCapacity': {
            'title': 'Maximum Storage Capacity',
            'type': 'number'
        }
    },
    'additionalProperties':false,
    'required':['title', 'storageType']
}

如果 storageTypeDVDHDD,我希望 minCapacitymaxCapacity 属性出现在 json 中如果 storageTypeNetwork.

,则不会出现在 json 中

如果我修改模式以将存储作为对象并将最小和最大容量作为其属性,则可以完成,如下面的模式所示。

{
    'title': 'storage schema',
    'description': 'storage schema',
    'type': 'object',
    'properties':{
        'title': {
            'title':'storage Name',
            'type': 'string',
            'minLength': 1,
            'maxLength': 255
        },
        'storage': {
            'title': 'storage Details',
            'type': 'object',
            'oneOf' : [{'$ref': '#/storage/disk'},
                       {'$ref': '#/storage/network'}]
        },
    },
    'additionalProperties':false,
    'required':['title', 'storage'],
    'storage':{
        'disk':{
            'properties':{
                'type': {
                    'title': 'Storage Type',
                    'enum': ['HDD', 'DVD']
                },
                'minCapacity': {
                    'title': 'Minimum Storage Capacity',
                    'type': 'number'
                },
                'maxCapacity': {
                    'title': 'Maximum Storage Capacity',
                    'type': 'number'
                }
            },
            'additionalProperties': false,
            'required':['type', 'minCapacity', 'maxCapacity']
        },
        'network':{
            'properties':{
                'type': {
                    'title': 'Storage Type',
                    'enum': ['Network', 'Internet']
                }
            },
            'additionalProperties': false,
            'required':['type']
        }
    }
}

但我想在不改变架构结构的情况下实现这一点。

可以做到吗?

有效Json1

{
    'title': 'additional mandatory properties',
    'storageType': 'HDD',
    'minCapacity': 0.1,
    'maxCapacity': 1
}

有效Json2

{
    'title': 'no additional mandatory properties',
    'storageType': 'Network'
}

无效Json1

{
    'title': 'additional mandatory properties',
    'storageType': 'Internet',
    'minCapacity': 0.1,
    'maxCapacity': 1
}

无效Json2

{
    'title': 'no additional mandatory properties',
    'storageType': 'HDD'
}

更新

当尝试来自 答案的架构时,仅在 json 中存在非必需参数之一时才进行验证。下面给出无效的JSON

无效Json3

{
    'title': 'additional mandatory properties',
    'storageType': 'Internet',
    'minCapacity': 0.1
}

无效Json4

{
    'title': 'additional mandatory properties',
    'storageType': 'Internet',
    'maxCapacity': 1
}

我通过对不需要部分的架构进行小修改解决了这个问题,如下所示。

{
    "title": "storage schema",
    "description": "storage schema",
    "type": "object",
    "properties": {
        "title": {
            "title": "storage Name",
            "type": "string",
            "minLength": 1,
            "maxLength": 255
        },
        "storageType": {
            "title": "storage Type"
        },
        "minCapacity": {
            "title": "Minimum Storage Capacity",
            "type": "number"
        },
        "maxCapacity": {
            "title": "Maximum Storage Capacity",
            "type": "number"
        }
    },
    "required": ["title", "storageType"],
    "anyOf": [
        {
            "properties": {
                "storageType": {
                    "enum": ["DVD", "HDD"]
                }
            },
            "required": ["minCapacity", "maxCapacity"]
        },
        {
            "properties": {
                "storageType": {
                    "enum": ["Network", "Internet"]
                }
            },
            "allOf":[
                {"not": {"required": ["maxCapacity"]}},
                {"not": {"required": ["minCapacity"]}}
            ]

        }
    ]
}

这是解决方案。

{
  "title": "storage schema",
  "description": "storage schema",
  "type": "object",
  "properties": {
    "title": {
      "title": "storage Name",
      "type": "string",
      "minLength": 1,
      "maxLength": 255
    },
    "storageType": {
      "title": "storage Type"
    },
    "minCapacity": {
      "title": "Minimum Storage Capacity",
      "type": "number"
    },
    "maxCapacity": {
      "title": "Maximum Storage Capacity",
      "type": "number"
    }
  },
  "additionalProperties": false,
  "required": ["title", "storageType"],
  "anyOf": [
    {
      "properties": {
        "storageType": {
          "enum": ["DVD", "HDD"]
        }
      },
      "required": ["minCapacity", "maxCapacity"]
    },
    {
      "properties": {
        "storageType": {
          "enum": ["Network", "Internet"]
        }
      },
      "not": { "required": ["maxCapacity", "minCapacity"] }
    }
  ]
}

P.S。 不鼓励使用 "additionalProperties": false。不得不像 #/anyOf/1/not 这样的事情就是一个例子,说明这个功能如何比它的价值更麻烦。最佳做法是简单地忽略不属于的属性。