【问题标题】:JSON schema: Why does "constant" not validate the same way as a single-valued "enum"?JSON 模式:为什么“常量”的验证方式与单值“枚举”不同?
【发布时间】:2018-07-01 13:56:33
【问题描述】:

我有一个对象,它提供了一种资产版本的审计日志。它的几个属性(versionSource.metadataversionSource.files)是应该针对两个模式之一进行验证的对象,具体取决于它们的属性之一的值。我开始在我的子模式中使用一个常量(在oneOf 内,但那是说所有子模式都经过验证(因此打破了oneOf,因为不止一个经过验证。将其更改为单值不过,枚举有效。

为什么在验证上有差异?

这是原始架构:

{
   "$id": "https://example.com/schemas/asset-version.json",
   "title": "Audit log of asset versions",
   "$schema": "http://json-schema.org/draft-07/schema",

   "type": "object",
   "required": [
      "assetID",
      "version",
      "versionSource"
   ],

   "properties": {
      "assetID": {
         "type": "string"
      },
      "version": {
         "type": "integer",
         "minimum": 1
      },
      "versionSource": {
         "type": "object",
         "properties": {
            "metadata": {
               "type": "object",
               "oneOf": [
                  {
                     "properties": {
                        "sourceType": { "constant": "client" }
                     }
                  },
                  {
                     "$ref": "#/definitions/version-source-previous-version"
                  }
               ]
            },
            "files": {
               "type": "object",
               "oneOf": [
                  {
                     "properties": {
                        "sourceType": { "constant": "upload" },
                        "sourceID": {
                           "type": "string"
                        }
                     }
                  },
                  {
                     "$ref": "#/definitions/version-source-previous-version"
                  }
               ]
            }
         }
      }
   },

   "definitions": {
      "version-source-previous-version": {
         "properties": {
            "sourceType": { "constant": "previous-version" },
            "sourceID": {
               "type": "integer",
               "minimum": 1
            }
         }
      }
   }
}

这是一个示例文档:

{
   "assetID": "0150a186-068d-43e7-bb8b-0a389b572379",
   "version": 1,
   "versionSource": {
      "metadata": {
         "sourceType": "client"
      },
      "files": {
         "sourceType": "upload",
         "sourceID": "54ae67b0-3e42-464a-a93f-3143b0f078fc"
      }
   },
   "created": "2018-09-01T00:00:00.00Z",
   "lastModified": "2018-09-02T12:10:00.00Z",
   "deleted": "2018-09-02T12:10:00.00Z"
}

还有一个:

{
   "assetID": "0150a186-068d-43e7-bb8b-0a389b572379",
   "version": 2,
   "versionSource": {
      "metadata": {
         "sourceType": "previous-version",
         "sourceID": 1
      },
      "files": {
         "sourceType": "previous-version",
         "sourceID": 1
      }
   },
   "created": "2018-09-01T00:00:00.00Z",
   "lastModified": "2018-09-02T12:10:00.00Z",
   "deleted": "2018-09-02T12:10:00.00Z"
}

这是我得到的错误:

消息:JSON 对来自“oneOf”的多个模式有效。有效架构索引:0、1。 架构路径: https://example.com/schemas/asset-version.json#/properties/versionSource/properties/metadata/oneOf

由于sourceTypeoneOf 内的两个架构中都是一个常量,我真的不确定我的对象如何可能对这两个架构都有效。

不过,将架构更改为以下内容是可行的:

{
   "$id": "https://example.com/schemas/asset-version.json",
   "title": "Audit log of asset versions",
   "$schema": "http://json-schema.org/draft-07/schema",

   "type": "object",
   "required": [
      "assetID",
      "version",
      "versionSource"
   ],

   "properties": {
      "assetID": {
         "type": "string"
      },
      "version": {
         "type": "integer",
         "minimum": 1
      },
      "versionSource": {
         "type": "object",
         "properties": {
            "metadata": {
               "type": "object",
               "oneOf": [
                  {
                     "properties": {
                        "sourceType": { "enum": [ "client" ] }
                     }
                  },
                  {
                     "$ref": "#/definitions/version-source-previous-version"
                  }
               ]
            },
            "files": {
               "type": "object",
               "oneOf": [
                  {
                     "properties": {
                        "sourceType": { "enum": [ "upload" ] },
                        "sourceID": {
                           "type": "string"
                        }
                     }
                  },
                  {
                     "$ref": "#/definitions/version-source-previous-version"
                  }
               ]
            }
         }
      }
   },

   "definitions": {
      "version-source-previous-version": {
         "properties": {
            "sourceType": { "enum": [ "previous-version" ] },
            "sourceID": {
               "type": "integer",
               "minimum": 1
            }
         }
      }
   }
}

我错过了什么?

【问题讨论】:

    标签: json jsonschema


    【解决方案1】:

    这是我自己的错字...constant 应该是const。 :facepalm:

    【讨论】:

      【解决方案2】:

      根据草案 7

      需要注意的是, const 只是单个元素枚举的语法糖,因此以下是等价的:

      { "const": "United States of America" }
      
      { "enum": [ "United States of America" ] }
      

      在某些渲染表单解决方案中使用default 键以选择单个选项时,有些人可能会觉得很有用。

      【讨论】:

        【解决方案3】:

        嗯.. 没有什么是不正确的。由于您使用的是 draft-07,您可以尝试使用 if/then/else 编写它,看看错误是否更有帮助。

        但是……

        您确定您使用的实现理解draft-07吗?如果它忽略 $schema 并通过 draft-04 规则运行它,它将无法理解const。你应该检查你的工具文档。

        【讨论】:

        • 我想出了如何让它工作(虽然我很确定在发布问题之前我已经尝试过)......从一个常量更改为一个单值枚举有效。有了这些信息,您能否深入了解其中的差异?也感谢您的快速回复!
        • 您确定您使用的实现理解draft-07吗?如果它忽略 $schema 并通过 draft-04 规则运行它,它将无法理解const。您需要为此检查您的工具文档,我只是使用规范:-)
        • 我在使用 AJV@6.0.1 时遇到了同样的错误,据说它支持 Draft-07。我也会通过github.com/epoberezkin/ajv 与 epoberezkin 联系。
        猜你喜欢
        • 2016-03-09
        • 2017-07-03
        • 1970-01-01
        • 2019-06-11
        • 1970-01-01
        • 2021-07-17
        • 2017-06-03
        • 2017-12-26
        • 1970-01-01
        相关资源
        最近更新 更多