强制数组内容的 JSON 模式

Posted

技术标签:

【中文标题】强制数组内容的 JSON 模式【英文标题】:JSON schema to enforce array contents 【发布时间】:2013-11-10 15:31:49 【问题描述】:

大家好,提前致谢。

我正在尝试创建一个 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 对象是任何仅包含属性“id”和“name”的有效 JSON 对象,其中“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 对象的名称值必须是字段 enum 中包含的值,其中 enum 包含单个值。

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



  "$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 的单个实例包含在我的数组中。

【问题讨论】:

AB 必须是前两个(按此顺序)吗?或者它们可以出现在列表中的任何位置? 【参考方案1】:

您要查找的内容称为“元组输入”。

如果items关键字的值是一个数组,那么数组数据中的项必须与对应位置的schema匹配。 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 关键字整齐地处理。)

更详细的现场演示:

Valid: [A, B] Invalid: [A, C] Valid: [A, B, C, C]

【讨论】:

这与我在下面得到的答案相匹配,并且是我为前进而实施的,尽管我希望它与位置无关。不过比你。从中我获得了元组类型的知识以及查看 Json Schema v5 的想法:) 如果您希望它与位置无关,您可以在 v4 中执行 something rather horrible。但是,我通常不建议这样做,因为它很难阅读/理解。 还值得注意的是,对于 v4 hack 和 v5 contains 关键字,约束是“至少 一个” - 而 additionalItems 不适用。对于 v5,有 a workaround 来指定一个。 能否请您链接 v5 的文档?我找不到它。 v5 规范实际上仍在编写中,尽管承诺很快。但是,各种建议的关键字已经在GitHub wiki 上。不能保证他们都能成功,但contains 几乎可以肯定。【参考方案2】:

我已经确定了一个解决我的问题的解决方案,强制 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 模式验证 JSON 数组,其中包含索引 0 处的 A 对象、索引 1 处的 B 对象和构成所有剩余元素的 C 对象。这个解决方案是可用的,并且允许我继续开发,尽管更喜欢一个独立于订单的解决方案。

感谢任何帮助! :)

PS - 这些模式没有优化,并展示了冗余,我将在最终版本中使用“id”和“$ref”关键字将其删除。

【讨论】:

顺便说一句 - 你不需要 $schema 在每个模式中,只需要***模式。 当面,相信现在是禁止的!

以上是关于强制数组内容的 JSON 模式的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 Azure 策略中主机名的名称模式?

Flutter:如何强制应用程序重启(在生产模式下)?

Json 模式数组大小参考

在 JSON 模式中定义枚举数组的正确方法

在 Hive 中,这种模式如何从 json 数组中识别嵌套的 json?

有没有办法强制 phpinfo() 输出其内容而不进行格式化。就像在 CLI 模式下一样?