voxpupuli / json-schema

Ruby JSON Schema Validator
MIT License
1.54k stars 243 forks source link

Broken defaults for oneOf #264

Open lumpidu opened 9 years ago

lumpidu commented 9 years ago

I have a schema with an array of oneOf $refs :

schema='{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "demo",
    "type": "object",
    "properties": {
        "formats": {
            "type": "array",
            "items": {
                "$ref": "#/definitions/format"
            }
        }
    },
    "definitions": {
        "format": {
            "oneOf": [
                {
                    "$ref": "#/definitions/format_ascii"
                },
                {
                    "$ref": "#/definitions/format_binary"
                }
            ]
        },
        "format_ascii": {
            "type": "object",
            "properties": {
                "encoding": {
                    "type": "string",
                    "enum": [
                        "ascii"
                    ],
                    "default": "ascii"
                },
                "scale": {
                    "type": "number",
                    "default": 1
                }
            },
            "additionalProperties": false
        },
        "format_binary": {
            "type": "object",
            "properties": {
                "encoding": {
                    "type": "string",
                    "enum": [
                        "binary"
                    ],
                    "default": "binary"
                },
                "order": {
                    "type": "string",
                    "enum": [
                        "little",
                        "big",
                        "network"
                    ]
                }
            },
            "required": [
                "order"
            ],
            "additionalProperties": false
        }
    }
}'

Here is valid data against the schema:

data = '{
    "formats": [ { "scale": 1}, { "order": "little"} ]
}'

Here is the validation part:

json = JSON.parse(data)
JSON::Validator.fully_validate(schema, json, :insert_defaults => true)

This generates wrongly added default data to the json variable:

puts json.inspect
{"formats"=>[{"scale"=>1, "encoding"=>"ascii"}, {"order"=>"little", "encoding"=>"ascii", "scale"=>1}]}

This is how it should be:

{"formats"=>[{"scale"=>1, "encoding"=>"ascii"}, {"order"=>"little", "encoding"=>"binary"}]}

And it does not even validate aigain successfully:

puts JSON::Validator.fully_validate(schema, json)

The property '#/formats/1' of type Hash did not match any of the required schemas. The schema specific errors were:

- oneOf #0:
    - The property '#/formats/1' contains additional properties ["order"] outside of the schema when none are allowed
- oneOf #1:
    - The property '#/formats/1' contains additional properties ["scale"] outside of the schema when none are allowed
    - The property '#/formats/1/encoding' value "ascii" did not match one of the following values: binary

Which leads me to think that there are in fact 2 issues:

The complete code can be found here: https://gist.github.com/lumpidu/e5ee62b46b16cdc688d1