用于强制执行数组内容的JSON模式

时间:2013-10-30 20:02:52

标签: arrays json validation schema jsonschema

大家好,并提前致谢。

我正在尝试创建一个JSON模式来强制数组包含一个A和B对象和N个C对象,其中A和B是C对象,N是包含在0和无穷大之间的整数。

因此:

[A, B] [A, B, C1] [A, B, C1, .., CN]

所有有效,但是:

[A] [A, C1] [A, C1, .., CN]

无效

要说清楚,A和B必须存在。 C对象是可选的,但您可以拥有任意数量的对象。

C对象架构:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "C Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  },
  "additionalProperties": false
}

所以C对象是任何有效的JSON对象,只包含属性“id”和“name”,其中“id”是一个整数,“name”是一个字符串。

A和B对象架构:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "A Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string",
      "enum": ["A"]
    }
  },
  "additionalProperties": false
}

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "B Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string",
      "enum": ["B"]
    }
  },
  "additionalProperties": false
}

A和B对象与C对象的不同之处在于强制执行名称值。 A对象的名称值必须是字段枚举中包含的值,其中枚举包含单个值。

我迄今为止最完整的架构是:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "To Date Solution",
  "description": "So far this is the most complete attempt at enforcing values to be contained within a JSON structure using JSON schemas.",

  "type": "array"
  "items": {
    "allOf": [
      {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "C Object",

        "type": "object",
        "required": ["id", "name"],

        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    ]
  }
}

这强制包含在其中的所有对象必须是C类,A和B是,但我不确定如何强制执行至少单个A和B实例包含在我的数组中。

2 个答案:

答案 0 :(得分:12)

您正在寻找的是“元组打字”。

如果items关键字的值是数组,则数组数据中的项必须与相应位置中的模式匹配。其他项目(超过最后一个索引)与additionalItems匹配(如果additionalItemsfalse,则不允许)。

所以,大概你想要的是:

{
    "type": "array",
    "items": [
        {"$ref": "#/definitions/itemTypeA"},
        {"$ref": "#/definitions/itemTypeB"}
    ],
    "additionalItems": {"$ref": "#/definitions/itemTypeC"},
    "definitions": {
        ... actual definitions for A/B/C ...
    }
}

如果您想确保存在A和B,那么您只需使用minItems指定最小长度,因此至少有两个项目(因为“元组输入”) ,必须与A和B匹配。

(这也假设A和B是数组中的第一项。如果这不是你想要的,那么它会变得有点复杂 - 虽然为v5提出了contains个关键字这将整齐地处理。)

稍微详细的现场演示:

答案 1 :(得分:1)

我已经确定了一个解决我的问题的解决方案,强制A和B存在于数组中,虽然这样做是有位置的,因此需要我验证的JSON对象以某种方式进行排序。

工作架构


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Order dependent solution",

  "type": "array",
  "items": [
    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "title": "A Object",

      "type": "object",
      "required": ["id", "name"],

      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "enum": ["A"]
        }
      },
      "additionalProperties": false
    },
    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "title": "B Object",

      "type": "object",
      "required": ["id", "name"],

      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "enum": ["B"]
        }
      },
      "additionalProperties": false
    }
  ],

  "additionalItems": {

    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "C Object",

    "type": "object",
    "required": ["id", "name"],

    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "string"
      }
    },
    "additionalProperties": false  
  }

}

此JSON模式验证包含索引0处的A对象,索引1处的B对象和组成所有剩余元素的C对象的JSON数组。这个解决方案是可用的,并且允许我继续开发,尽管优先选择顺序独立的解决方案。

任何帮助表示赞赏! :)

PS - 这些模式未经过优化,并且演示了冗余,我将通过使用“id”和“$ ref”关键字在最终版本中删除。