Home > OS >  Json.NET Schema fails in not validating json based on schema
Json.NET Schema fails in not validating json based on schema

Time:07-01

I'm trying to use Json.NET Schema to validate some JSONs against a schema I constructed and validated using JSON Schema Validator - https://www.jsonschemavalidator.net/, which is a demo of this library and https://www.liquid-technologies.com/online-json-schema-validator. Both of them worked in validating my JSONs.

When I tried to do the same thing in .NET, it validates all the inputs I put there even if it shouldn't. I'll write below my schema and the input I'm trying to use which should return some errors but it's not. You can change the inputs accordingly for testing purposes.

Schema:

    "$schema": "http://json-schema.org/draft-04/schema#",
    "$id": "https://example.com/form.schema.json",
    "title": "Title",
    "description": "Description",
    "type": "object",
    "properties":{
        "inputs": {
            "description": "List of inputs",
            "type": "array",
            "items": {
                "description": "Input object",
                "type": "object",
                "properties": {
                    "type": {
                        "description": "The type of the input field",
                        "type": "string",
                        "enum": [
                            "text",
                            "text-area",
                            "email",
                            "number",
                            "file",
                            "date",
                            "phone",
                            "checkbox",
                            "radio",
                            "dropdown",
                            "password",
                            "range",
                            "time"
                        ]
                    },
                    "value": {
                        "description": "Default value of the field",
                        "type": "string"
                    },
                    "id": {
                        "description": "Id of the field",
                        "type": "string"
                    },
                    "label": {
                        "description": "Label of the field",
                        "type": "string"
                    },
                    "placeholder": {
                        "description": "Placeholder of the field",
                        "type": "string"
                    },
                    "required": {
                        "description": "Boolean saying if the field is required or not",
                        "type": "boolean",
                        "default": false
                    },
                    "help": {
                        "description": "Help text to be displayed",
                        "type": "string"
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "description": "List of options",
                            "type": "string"
                        },
                    "minItems": 1,
                    "uniqueItems": true
                    },
                    "accept": {
                        "description": "Accepted file types",
                        "type": "array",
                        "items": {
                            "description": "List of accepted file types",
                            "type": "string",
                            "enum": [
                                ".pdf",
                                ".jpg",
                                ".doc"
                            ]
                        }
                    },
                    "multiple": {
                        "description": "Boolean saying if the form accepts multiple files or not",
                        "type": "boolean",
                        "default": false
                    },
                    "step": {
                        "description": "Step of the number input",
                        "type": "number",
                        "default": 1
                    },
                    "min": {
                        "description": "Minimum of the number input",
                        "type": "number"
                    },
                    "max": {
                        "description": "Maximum of the number input",
                        "type": "number"
                    }
                },
                "required": [
                    "type",
                    "id",
                    "label",
                    "required"
                ],
                "oneOf": [
                  {
                      "properties": { "type": { "enum": ["text", "text-area", "email", "date", "phone", "checkbox", "password", "time"] } }
                  },
                  {
                      "properties": { "type": { "enum": ["radio", "dropdown"] } },
                      "required": ["options"]
                  },
                  {

                      "properties": { "type": { "const": "file" } },
                      "required": ["accept", "multiple"]
                  },
                  {
                      "properties": { "type": { "const": "number" } },
                      "required": ["step"]
                  },
                  {
                      "properties": { "type": { "const": "range" }},
                      "required": ["min", "max"]
                  }
                ]
            }
        }
    }
}

JSON input:

   "inputs": [
       {
           "type": "number",
           "value": "Example text",
           "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
           "label": "First Name",
           "placeholder": "Some placeholder",
           "required": true
       },
       {
           "type": "radio",
           "value": "Example text",
           "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
           "label": "First Name",
           "placeholder": "Some placeholder",
           "required": true,
           "options": ["option1", "options2"],
           "min": 1,
           "max": 5
       }
   ]
}

Is something I'm doing wrong in writing the schema? I also tried to use conditionals - if, then, else for requiring some fields but those ones couldn't be validated even in the online validators:

    "$schema": "http://json-schema.org/draft-04/schema#",
    "$id": "https://example.com/form.schema.json",
    "title": "Record of a form",
    "description": "This document records the details of a form",
    "type": "object",
    "properties":{
        "inputs": {
            "description": "List of inputs",
            "type": "array",
            "items": {
                "description": "Input object",
                "type": "object",
                "properties": {
                    "type": {
                        "description": "The type of the input field",
                        "type": "string",
                        "enum": [
                            "text",
                            "text-area",
                            "email",
                            "number",
                            "file",
                            "date",
                            "phone",
                            "checkbox",
                            "radio",
                            "dropdown",
                            "password",
                            "range",
                            "time"
                        ]
                    },
                    "value": {
                        "description": "Default value of the field",
                        "type": "string"
                    },
                    "id": {
                        "description": "Id of the field",
                        "type": "string"
                    },
                    "label": {
                        "description": "Label of the field",
                        "type": "string"
                    },
                    "placeholder": {
                        "description": "Placeholder of the field",
                        "type": "string"
                    },
                    "required": {
                        "description": "Boolean saying if the field is required or not",
                        "type": "boolean",
                        "default": false
                    },
                    "help": {
                        "description": "Help text to be displayed",
                        "type": "string"
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "description": "List of options",
                            "type": "string"
                        },
                    "minItems": 1,
                    "uniqueItems": true
                    },
                    "accept": {
                        "description": "Accepted file types",
                        "type": "array",
                        "items": {
                            "description": "List of accepted file types",
                            "type": "string",
                            "enum": [
                                ".pdf",
                                ".jpg",
                                ".doc"
                            ]
                        }
                    },
                    "multiple": {
                        "description": "Boolean saying if the form accepts multiple files or not",
                        "type": "boolean",
                        "default": false
                    },
                    "step": {
                        "description": "Step of the number input",
                        "type": "number",
                        "default": 1
                    },
                    "min": {
                        "description": "Minimum of the number input",
                        "type": "number"
                    },
                    "max": {
                        "description": "Maximum of the number input",
                        "type": "number"
                    }
                },
                "required": [
                    "type",
                    "id",
                    "label",
                    "required"
                ],
                "allOf": [
                {
                    "if": {
                        "properties": { "type": { "enum": ["radio", "dropdown"] } }
                    },
                    "then": {
                        "required": ["options"]
                    },
                    "else": false
                },
                {
                    "if": {
                        "properties": { "type": {"const": "number" } }
                    },
                    "then": {
                        "required": ["step"]
                    },
                    "else": false
                },
                {
                    "if": {
                        "properties": { "type": {"const": "file" } }
                    },
                    "then": {
                        "required": ["multiple", "accept"]
                    },
                    "else": false
                },
                {
                    "if": {
                        "properties": { "type": {"const": "range" } }
                    },
                    "then": {
                        "required": ["min", "max"]
                    },
                    "else": false
                }
                ]
            }
        }
    }
}

CodePudding user response:

if/then is a better alternative than oneOf, but you can't use it with a draft-04 schema. If you can upgrade to draft-07, you can use the conditional statements. You can do this by changing the value of the $schema keyword. Just change the "4" to a "7".

Next, drop the else keywords. If you use else, the conditional evaluates to false if the if doesn't match. Since you are using allOf, if any of the conditionals evaluates to false, the schema will fail. That's not what you want because your JSON will always fail validation because not all of the conditionals can pass at the same time.

Optionally, for better error messages, add "required": ["type"] to each of your conditionals. This allows for better error messages if the "type" property is missing from the object.

Optionally, for better error messages, add "type": "object" to each of your conditional. This allows for better error messages if you are validating something that isn't an object.

  • Related