JSON模式 - 动态必需属性

时间:2015-07-29 14:19:10

标签: json jsonschema

我有一个架构来验证传入的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']
}

如果minCapacitymaxCapacitystorageType并且json中不存在,我希望json中存在DVDHDD属性如果storageTypeNetwork

如果我修改架构以将存储作为对象并且具有最小和最大容量作为其属性,则可以执行此操作,如下面的架构中所示。

{
    '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']
        }
    }
}

但我希望在不改变架构结构的情况下实现这一目标。

可以吗?

有效的Json 1

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

有效的Json 2

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

Json 1无效

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

Json 2无效

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

更新

jason's回答尝试模式时,它没有验证何时,json中存在一个非必需参数。下面给出了无效的JSON。

Json 3无效

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

Json 4无效

{
    '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"]}}
            ]

        }
    ]
}

1 个答案:

答案 0 :(得分: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"
    }
  },
  "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之类的东西就是这个功能如何比它的价值更麻烦的一个例子。最佳做法是简单地忽略不属于的属性。