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

How to validate if the schema itself is valid? #481

Open
iiliev2 opened this issue Mar 2, 2023 · 7 comments
Open

How to validate if the schema itself is valid? #481

iiliev2 opened this issue Mar 2, 2023 · 7 comments

Comments

@iiliev2
Copy link

iiliev2 commented Mar 2, 2023

Is the schema loader supposed to throw if the input is not a valid(DRAFT4-7) schema? org.everit.json.schema.loader.SchemaLoader#load(org.json.JSONObject). I can't find any relevant javadocs explaining this.

@erosb
Copy link
Contributor

erosb commented Mar 2, 2023

Hello @iiliev2 please check this section of the manual, thanks.

@iiliev2
Copy link
Author

iiliev2 commented Mar 2, 2023

Hi, I don't understand how that section answers the question? I am asking how to validate if the schema itself is valid. Not how to tell which schema version to load against.

@erosb
Copy link
Contributor

erosb commented Mar 2, 2023

If you want to validate your schema json against any specification version, you can download the meta-schema of the spec, and validate your schema against the meta-schema.

@iiliev2
Copy link
Author

iiliev2 commented Mar 2, 2023

Thanks. Can I do that via SchemaLoader.load(meta-schema).validate(my-schema)?

We are currently not doing that and are instead just trying to load my-schema. So I wanted to know what is supposed to happen if the input is invalid. And if that behaviour is supposed to be an official part of the javadoc, or it could change in future versions.

@erosb
Copy link
Contributor

erosb commented Mar 2, 2023

Can I do that via SchemaLoader.load(meta-schema).validate(my-schema)?

Mostly yes although I'm not sure what is the schema version of the meta-schemas (but they should state it in their root-level "$schema" property).

So you can use this meta-schema based approach.

Yet, if you don't use that, the SchemaLoader has its type-safe internals and will provide meaningful error information in most cases, by throwing a SchemaException instance, which provides a programmer-friendly description of the error, plus a pointer denoting the place in the schema json where the error was found.

One important thing to be aware of is that if you have misspelled property names in the schema (like "typ" instead of "type"), then those won't be reported by any of the above approaches (the meta-schemas all permit additional properties in schemas, hence the SchemaLoader doesn't complain about them either).

I hope this fully answers your question :)

@iiliev2
Copy link
Author

iiliev2 commented Mar 2, 2023

I wrote a simple unit test to illustrate what would happen if I try to validate an invalid schema, but it does not fail as expected. What am I doing wrong? Using version 1.14.1:

    private static final JsonMapper MAPPER = new JsonMapper();

    @Test(expectedExceptions = Exception.class)
    void failValidateInvalidSchemaV4() throws IOException {
        var metaSchema = new JSONObject(load("json-schema-v4.json"));
        var mySchema = new JSONObject(load("invalid-schema.json"));
        SchemaLoader.load(new JSONObject(metaSchema)).validate(mySchema);
    }

    Map<String,Object> load(String json) throws IOException {
        return MAPPER.readValue(
                getClass().getResourceAsStream(json),
                new TypeReference<HashMap<String, Object>>() {}
        );
    }

json-schema-v4.json(meta schema)

{
  "id": "http://json-schema.org/draft-04/schema#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Core schema meta-schema",
  "definitions": {
    "schemaArray": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#" }
    },
    "positiveInteger": {
      "type": "integer",
      "minimum": 0
    },
    "positiveIntegerDefault0": {
      "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
    },
    "simpleTypes": {
      "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
    },
    "stringArray": {
      "type": "array",
      "items": { "type": "string" },
      "minItems": 1,
      "uniqueItems": true
    }
  },
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "$schema": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "default": {},
    "multipleOf": {
      "type": "number",
      "minimum": 0,
      "exclusiveMinimum": true
    },
    "maximum": {
      "type": "number"
    },
    "exclusiveMaximum": {
      "type": "boolean",
      "default": false
    },
    "minimum": {
      "type": "number"
    },
    "exclusiveMinimum": {
      "type": "boolean",
      "default": false
    },
    "maxLength": { "$ref": "#/definitions/positiveInteger" },
    "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
    "pattern": {
      "type": "string",
      "format": "regex"
    },
    "additionalItems": {
      "anyOf": [
        { "type": "boolean" },
        { "$ref": "#" }
      ],
      "default": {}
    },
    "items": {
      "anyOf": [
        { "$ref": "#" },
        { "$ref": "#/definitions/schemaArray" }
      ],
      "default": {}
    },
    "maxItems": { "$ref": "#/definitions/positiveInteger" },
    "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
    "uniqueItems": {
      "type": "boolean",
      "default": false
    },
    "maxProperties": { "$ref": "#/definitions/positiveInteger" },
    "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
    "required": { "$ref": "#/definitions/stringArray" },
    "additionalProperties": {
      "anyOf": [
        { "type": "boolean" },
        { "$ref": "#" }
      ],
      "default": {}
    },
    "definitions": {
      "type": "object",
      "additionalProperties": { "$ref": "#" },
      "default": {}
    },
    "properties": {
      "type": "object",
      "additionalProperties": { "$ref": "#" },
      "default": {}
    },
    "patternProperties": {
      "type": "object",
      "additionalProperties": { "$ref": "#" },
      "default": {}
    },
    "dependencies": {
      "type": "object",
      "additionalProperties": {
        "anyOf": [
          { "$ref": "#" },
          { "$ref": "#/definitions/stringArray" }
        ]
      }
    },
    "enum": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true
    },
    "type": {
      "anyOf": [
        { "$ref": "#/definitions/simpleTypes" },
        {
          "type": "array",
          "items": { "$ref": "#/definitions/simpleTypes" },
          "minItems": 1,
          "uniqueItems": true
        }
      ]
    },
    "format": { "type": "string" },
    "allOf": { "$ref": "#/definitions/schemaArray" },
    "anyOf": { "$ref": "#/definitions/schemaArray" },
    "oneOf": { "$ref": "#/definitions/schemaArray" },
    "not": { "$ref": "#" }
  },
  "dependencies": {
    "exclusiveMaximum": [ "maximum" ],
    "exclusiveMinimum": [ "minimum" ]
  },
  "default": {}
}

invalid-schema.json("type": "any" is invalid as is even highlighted in IntelliJ):

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "my json api",
  "description": "my json api",
  "type": "object",
  "properties": {
    "my_api_response": {
      "type": "object",
      "properties": {
        "MailboxInfo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "ADSyncLinkEnabled": {
                "type": "any"
              }
            }
          }
        }
      }
    }
  },
  "required": ["response"]
}

@erosb
Copy link
Contributor

erosb commented Mar 3, 2023

Odd. An invalid "type" should throw an exception.

Hopefully I will have time to have a deeper look over the weekend.

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

2 participants