jsonSchema attribute conditionally required depend

2020-03-29 07:43发布

问题:

Per this question jsonschema attribute conditionally required, I can apply conditional required properties. However, it can only depend on the properties on the same level of object. In certain case, I want to one property required depend on its parent object property, is it possible? For the below example:

{
  type: 'object',
  properties: {
    { 
      os: { type: 'string', enum: ['macOs', 'windows'] },
      specs: {
        macModel: { 
          type: 'string', 
          enum: ['macbook air', 'macbook pro', 'macbook']
        },
        memory: { type: 'number' }
      }
    }
  }
}

Is it possible to meet this requirement: /spec/macModel is required only when /os equals to macOs?

回答1:

Yes, the same approach applies. You just need to nest schemas a little deeper.

{
  "type": "object",
  "properties": {
    "os": { "enum": ["macOs", "windows"] },
    "specs": {
      "macModel": { "enum": ["macbook air", "macbook pro", "macbook"] },
      "memory": { "type": "number" }
    }
  },
  "allOf": [{ "$ref": "#/definitions/os-macOs-requires-macModel" }],
  "definitions": {
    "os-macOs-requires-macModel": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/os-macOs" } },
        { "$ref": "#/definitions/requires-macModel" }
      ]
    },
    "os-macOs": {
      "properties": {
        "os": { "const": "macOs" }
      },
      "required": ["os"]
    },
    "requires-macModel": {
      "properties": {
        "specs": {
          "required": ["macModel"]
        }
      }
    }
  }
}

Notice that in the /definitions/requires-macModel schema it has to dig into the "specs" property and place the required there instead of at the top level as it is in the flat case.

I've used the implication pattern for this example, but the same approach can be taken with if-then if you prefer that approach and have access to a draft-07 validator.