【问题标题】:How to tell JSON schema validator to pick schema from property value?如何告诉 JSON 模式验证器从属性值中选择模式?
【发布时间】:2013-10-17 01:39:29
【问题描述】:

例如文件系统的架构,目录包含文件列表。该模式由文件规范、下一个子类型“图像”和另一个“文本”组成。

底部是主目录架构。目录有一个属性内容,它是一个项目数组,应该是文件的子类型。

基本上,我正在寻找一种方法来告诉验证器从正在验证的 json 对象的属性中查找“$ref”的值。

示例 json:

{
    "name":"A directory",
    "content":[
        {
            "fileType":"http://x.y.z/fs-schema.json#definitions/image",
            "name":"an-image.png",
            "width":1024,
            "height":800
        }
        {
            "fileType":"http://x.y.z/fs-schema.json#definitions/text",
            "name":"readme.txt",
            "lineCount":101
        }
        {
            "fileType":"http://x.y.z/extended-fs-schema-video.json",
            "name":"demo.mp4",
            "hd":true
        }

    ]
}

“伪”架构请注意,“图像”和“文本”定义包含在同一架构中,但它们可能在其他地方定义

{
    "id": "http://x.y.z/fs-schema.json",
    "definitions": {
        "file": {
            "type": "object",
            "properties": {
                "name": { "type": "string" },
                "fileType": {
                    "type": "string",
                    "format": "uri"
                }
            }
        },
        "image": {
            "allOf": [
            { "$ref": "#definitions/file" },
            {
                "properties": {
                    "width": { "type": "integer" },
                    "height": { "type": "integer"}
                }
            }
            ]
        },
        "text": {
            "allOf": [
            { "$ref": "#definitions/file" },
            { "properties": { "lineCount": { "type": "integer"}}}
            ]
        }
    },
    "type": "object",
    "properties": {
        "name": { "type": "string"},
        "content": {
            "type": "array",
            "items": {
                "allOf": [
                { "$ref": "#definitions/file" },
                { *"$refFromProperty"*: "fileType" } // the magic thing
                ]
            }
        }
    }
}

【问题讨论】:

  • 需要澄清。您想强制目录中的所有文件项都满足在定义目录数据时(不是在设计时)定义的某些属性,对吗?
  • 我希望它从属性 fileType 中为文件的子类型选择正确的定义

标签: json inheritance jsonschema


【解决方案1】:

仅 JSON Schema 的验证部分无法做到这一点 - 它代表一个固定的结构。您需要在验证时解析/引用架构。

但是,您可以使用 JSON Hyper-Schema 和 rel="describedby" 链接来表达这一点:

{
    "title": "Directory entry",
    "type": "object",
    "properties": {
        "fileType": {"type": "string", "format": "uri"}
    },
    "links": [{
        "rel": "describedby",
        "href": "{+fileType}"
    }]
}

所以这里,它从"fileType" 中获取值,并使用它来计算与关系“describeby”的链接——这意味着“该位置的架构也描述了当前数据”。

问题在于大多数验证器不会注意到任何链接(包括“描述的”链接)。你需要找到一个“超级验证器”。

更新tv4 库已将此作为一项功能添加

【讨论】:

  • 谢谢,这似乎可以解决问题,尽管我仍然需要按照你说的找到“超级验证器”,或者自己动手!
  • 感谢云脚!这就是我正在寻找的答案。 describeBy 让我维护一个解耦模式。我正在使用插值来计算 URI,我假设我也可以对 describeBy rel 的 href 值使用插值,如上所示。感谢您发布答案!
  • 你知道任何支持这个的 JS 验证器吗?
  • 我相信这种事情是this project 的目标之一,但我不知道它处于什么状态。另一方面,如果您在tv4 GitHub page 上提出问题,很有可能会被放进去。
【解决方案2】:

我认为 cloudfeet 的答案是一个有效的解决方案。您也可以使用相同的方法described here

您将拥有一个文件对象类型,它可以是您想要定义的所有子类型的“anyOf”。您将使用枚举以便能够针对每个子类型进行引用和验证。

如果子类型架构在同一个 Json-Schema 文件中,则不需要使用“$ref”显式引用 uri。正确的 draft4 验证器将找到枚举值,并尝试针对 Json-Schema 树中的“子模式”进行验证。

draft5(进行中)中提出了一个“switch”语句,这将允许以更明确的方式表达替代方案。

【讨论】:

  • 枚举不是一个选项,因为我在创作时不知道所有可能的子类型。我知道“图像”和“文本”,但有人可能会在他们自己的单独架构中添加“文件”的子类型。在将映射“文件”的 OOP 中,将映射到接口或抽象 api 类。
  • 我认为这没有问题。扩展接口的具有附加枚举值的信息,并且它可以以与 OOP 中相同的方式强制它们,扩展具有基本接口和扩展的知识。
  • 我想我不明白。如果您将枚举用于子类型中的 (fileType) 属性,则可以,但该模式将验证不需要的“fileType”的任何值...另一方面,“OOP 扩展的具有基本接口的知识,并且扩展”。不,您不必知道其他扩展是什么来制作您自己的基本抽象类扩展或实现接口:)
  • 我看到了不同的可能性:基“类”使用“anyOf/oneOf”进行限制,派生类使用另一个“anyOf/oneOf”对允许的枚举类型进行更多限制。如果您希望继承基类型,那么我会尝试在运行时动态地构建模式的联合。这在您的情况下可行吗? PD我想像你说的那样表达“和自己的扩展”。
  • 没错,就像您在运行时所说的那样构建联合模式。这可能是一种选择。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-10-29
  • 2019-01-28
  • 1970-01-01
  • 2019-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多