How to tell JSON schema validator to pick schema from property value?

做~自己de王妃 提交于 2019-12-17 16:35:18

问题


For example a schema for a file system, directory contains a list of files. The schema consists of the specification of file, next a sub type "image" and another one "text".

At the bottom there is the main directory schema. Directory has a property content which is an array of items that should be sub types of file.

Basically what I am looking for is a way to tell the validator to look up the value of a "$ref" from a property in the json object being validated.

Example 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
        }

    ]
}

The "pseudo" Schema note that "image" and "text" definitions are included in the same schema but they might be defined elsewhere

{
    "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
                ]
            }
        }
    }
}

回答1:


The validation parts of JSON Schema alone cannot do this - it represents a fixed structure. What you want requires resolving/referencing schemas at validation-time.

However, you can express this using JSON Hyper-Schema, and a rel="describedby" link:

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

So here, it takes the value from "fileType" and uses it to calculate a link with relation "describedby" - which means "the schema at this location also describes the current data".

The problem is that most validators do not take any notice of any links (including "describedby" ones). You need to find a "hyper-validator" that does.

UPDATE: the tv4 library has added this as a feature




回答2:


I think cloudfeet answer is a valid solution. You could also use the same approach described here.

You would have a file object type which could be "anyOf" all the subtypes you want to define. You would use an enum in order to be able to reference and validate against each of the subtypes.

If the sub-types schemas are in the same Json-Schema file you don't need to reference the uri explicitly with the "$ref". A correct draft4 validator will find the enum value and will try to validate against that "subschema" in the Json-Schema tree.

In draft5 (in progress) a "switch" statement has been proposed, which will allow to express alternatives in a more explicit way.



来源:https://stackoverflow.com/questions/19416873/how-to-tell-json-schema-validator-to-pick-schema-from-property-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!