Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schemas with references ($ref) not working and always passing #16

Open
guillemdc opened this issue Oct 13, 2014 · 6 comments
Open

schemas with references ($ref) not working and always passing #16

guillemdc opened this issue Oct 13, 2014 · 6 comments

Comments

@guillemdc
Copy link

I have schemas that reference other Ids in the same schema and they always validate, even when they shouldn't.

For example this data:

{
"name": "Joe",
"toys": [{
    "name": "car",
    "price": 23
}]
}

will validate against this schema, but it shouldn't because the toy has no color.

{
    "kid": {
        "id": "kid",
        "required": ["name",
        "toys"],
        "properties": {
            "name": {
                "type": "string"
            },
            "toys": {
                "type": "array",
                "items": {
                    "$ref": "toy"
                }
            }
        }
    },
    "toy": {
        "id": "toy",
        "required": ["name",
        "price",
        "color"],
        "properties": {
            "name": {
                "type": "string"
            },
            "price": {
                "type": "integer"
            },
            "color": {
                "type": "string"
            }
        }
    }
}
@KrekkieD
Copy link

Your schema is not a valid v4 schema. You should probably use definitions to refer to other schemas.

See https://json-schema-validator.herokuapp.com/syntax.jsp for a schema validator. The syntax you use is fine, but you need to use the v4 schema format.

Something like this should work better:

{
    "allOf": [
        {"$ref": "#/definitions/kid"}
    ],
    "definitions": {
        "kid": {
            "required": [
                "name",
                "toys"
            ],
            "properties": {
                "name": {
                    "type": "string"
                },
                "toys": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/toy"
                    }
                }
            }
        },
        "toy": {
            "required": [
                "name",
                "price",
                "color"
            ],
            "properties": {
                "name": {
                    "type": "string"
                },
                "price": {
                    "type": "integer"
                },
                "color": {
                    "type": "string"
                }
            }
        }
    }
}

@guillemdc
Copy link
Author

Hi KrekkieD,

Thanks for such a quick response! I'm using this library in a server to validate the input of a client that uses an API documented with Swagger. I basically used the same syntax and format they use in their examples:

Here it's how it works: http://petstore.swagger.wordnik.com/#!/pet
Here, the element "models" is supposed to contain a json schema that represents the objects used in that API.

I'm afraid that, if I change the way I wrote the schema, the GUI would not work anymore. By the looks of the schema I'm using, would you be able to tell what version is? That way I'll find the correct validator.

@KrekkieD
Copy link

Hi guillemdc,

I'm only familiar with the v4 schema.

It doesn't look that bad really, but json schema requires you to put properties within a properties property. What you have in Swagger appears to be a sample json structure (kind of like a blueprint or template), and not a json schema that actually describes the json structure. I'm not sure if Swagger will play with json schema, I'm not familiar with Swagger.

Basically the schemas always have a predefined format, which can be 'complicated' by nesting or using references. The schema itself has keywords that you should follow (i.e. allOf, properties, type, etc.), and within some of these you may define the properties that you want to validate (i.e. the schema properties object kan have custom properties that match your object keys (see my example above, I used name, price, color), but the properties within that object uses the fixed schema keys (in the example I used type, items)).

Any implementation of the v4 schema knows those fixed keys and the format of the schema. This is the key principle, as this is what defines the standard! moving away from this moves you away from the v4 schema, which means 99% of open source solutions won't work for you.

@guillemdc
Copy link
Author

I asked in the swagger github (you have the reference right above) and they told me they use a subset of the schema, and not all of it, so it's obvious that it's not an issue in your library. I guess that's the reason why it doesn't work and I shouldn't be relying on the models included in the swagger file to automate the validation, but that means creating two schemas, one in the swagger format and one in the official JSON schema one.

Edit: Swagger 1.2 uses a different schema. Moving to 2.0 should solve the issue. You can close this thread. Thank you very much for the support!

@hielsnoppe
Copy link

I am experiencing the same issue though using v4 syntax:

<?php

include('vendor/autoload.php');

use \Jsv4\Validator;

$data = '{
    "foo": "bar"
}';

$schema = '{
    "type": "object",
    "definitions": {
        "nonNegativeInteger": {
            "type": "integer",
            "minimum": 0
        }
    },
    "properties": {
        "foo": {
            "$ref": "#/definitions/nonNegativeInteger"
        }
    }
}';

$data = json_decode($data);
$schema = json_decode($schema);

$result = Validator::validate($data, $schema);

var_dump($result);

This results in bool(true) in contrast to when I change the $schema to

$schema = '{
    "type": "object",
    "properties": {
        "foo": {
            "type": "integer",
            "minimum": 0
        }
    }
}';

which results in bool(false) as expected.

@ypollart
Copy link

Hi @hielsnoppe, we've been facing the exact same problem.
The thing is: jsv4 does not resolve any reference when validating. There is a workaround using the SchemaStore class. Here are some simple steps

  • First, add your schema to the SchemaStore;
  • Then, call Validator::validate() with the schema coming from the store.

Here is an example (I did not try it but it should be pretty ok, you got the idea):

$schema = '{
    "id": "http://schema.example.com/your/id/here",
    "type": "object",
    "definitions": {
        "nonNegativeInteger": {
            "type": "integer",
            "minimum": 0
        }
    },
    "properties": {
        "foo": {
            "$ref": "#/definitions/nonNegativeInteger"
        }
    }
}';

$schema = json_decode($schema);
$store = new SchemaStore();

// $url must match the id property of your schema
$url = "http://schema.example.com/your/id/here";
$store->add($url, $schema);

$result = Validator::validate($data, $store->get($url));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants