Giter VIP home page Giter VIP logo

Comments (10)

justin-tay avatar justin-tay commented on June 26, 2024 2

The JSON Schema doesn't describe what you are expecting. The required keyword should be an array of property keys required and is not a boolean value.

{
  "type": "object",
  "properties": {
    "age": {
      "type": "number"
    },
    "user": {
      "type": "object",
      "oneOf": [
        {
          "properties": {
            "name": {
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "additionalProperties": false
        },
        {
          "properties": {
            "id": {
              "type": "number"
            }
          },
          "required": [
            "id"
          ],
          "additionalProperties": false
        }
      ]
    }
  },
  "required": [
    "age",
    "user"
  ]
}

https://www.jsonschemavalidator.net/s/ouhgFpSx

from json-schema-validator.

Yuutakasan avatar Yuutakasan commented on June 26, 2024 1

@justin-tay I am working on the test data now, so please wait a moment.

from json-schema-validator.

justin-tay avatar justin-tay commented on June 26, 2024

Can you provide unit test cases or at least the schema and data to elaborate on what errors you are encountering with this? I have tried but don't see anything unusual.

package com.networknt.schema;

import java.util.Set;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.networknt.schema.SpecVersion.VersionFlag;

/**
 * Tests for nested applicators.
 */
public class NestedApplicatorTest {
    @Test
    void anyOfOneOfOneOfFalse() {
        String schemaData = "{\r\n"
                + "  \"anyOf\": [\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertFalse(messages.isEmpty());
    }

    @Test
    void anyOfOneOfOneOfTrue() {
        String schemaData = "{\r\n"
                + "  \"anyOf\": [\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertTrue(messages.isEmpty());
    }

    @Test
    void allOfOneOfAnyOfFalse() {
        String schemaData = "{\r\n"
                + "  \"allOf\": [\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"anyOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertFalse(messages.isEmpty());
    }

    @Test
    void allOfOneOfAnyOfTrue() {
        String schemaData = "{\r\n"
                + "  \"allOf\": [\r\n"
                + "    {\r\n"
                + "      \"oneOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"anyOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertTrue(messages.isEmpty());
    }

    @Test
    void oneOfAllOfAnyOfFalse() {
        String schemaData = "{\r\n"
                + "  \"oneOf\": [\r\n"
                + "    {\r\n"
                + "      \"allOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"anyOf\": [\r\n"
                + "        false,\r\n"
                + "        false\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertFalse(messages.isEmpty());
    }

    @Test
    void oneOfAllOfAnyOfTrue() {
        String schemaData = "{\r\n"
                + "  \"oneOf\": [\r\n"
                + "    {\r\n"
                + "      \"allOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    },\r\n"
                + "    {\r\n"
                + "      \"anyOf\": [\r\n"
                + "        false,\r\n"
                + "        true\r\n"
                + "      ]\r\n"
                + "    }\r\n"
                + "  ]\r\n"
                + "}";
        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);
        Set<ValidationMessage> messages = schema.validate("{}", InputFormat.JSON);
        Assertions.assertTrue(messages.isEmpty());
    }
}

from json-schema-validator.

justin-tay avatar justin-tay commented on June 26, 2024

Given your test examples I don't see the issue. It looks like your issue is because you are placing type: object everywhere which is going to affect the result.

Take the following for instance

    Example1:
      anyOf:
      - type: object
      - $ref: '#/components/schemas/SampleData1'
      - $ref: '#/components/schemas/SampleData2'
      description: ""
      type: object

Because you placed type: object under anyOf, as long as an object is input the result will always validate successfully. This is also different from your diagram where you only have 2 children. There are instead 3 children of anyOf of which one is type: object. This applies to all your other examples where type: object is a child of anyOf, allOf and oneOf.

from json-schema-validator.

ItouTerukazu avatar ItouTerukazu commented on June 26, 2024

@justin-tay
Attached are the json-schema and json-data for the cases where the behavior is questionable.
Thank you very much for your confirmation.

image

If the element names in the json are the same

  "Example1_1" : {
        "type" : "object",
        "allOf" : [
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "data" : {
                                "type" : "string"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "data" : {
                                "type" : "number"
                            }
                        }
                    }
                ]
            },
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "data" : {
                                "type" : "boolean"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "data" : {
                                "type" : "string",
                                "enum" : [
                                    "value1",
                                    "value2"
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }

test data
 json data
 - case1 : The values are all null. anyOf setting would cause an error if all elements are null.

     "exampleX_1_0" : {




     },

 - case2 : The first and second child elements are null, but there is no error (should be an error)

    "exampleX_1_8" : {



        "data" : "value1"
    },

  ※If ↓, an error occurs at AnyOf.

   "exampleX_1_1" : {
        "data" : "data"



     },

 - case3 : The first and second child elements are null, but there is no error (should be an error)

    "exampleX_1_c" : {


        "data" : true,
        "data" : "value1"
    },
※If ↓, an error occurs at AnyOf.
     "exampleX_1_3" : {
         "data" : "data",
         "data" : 1
 
 
     },

If the Json element names are all disjoint

    "Example1_2" : {
        "type" : "object",
        "allOf" : [
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "dataA" : {
                                "type" : "string"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "dataB" : {
                                "type" : "number"
                            }
                        }
                    }
                ]
            },
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "dataC" : {
                                "type" : "boolean"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "dataD" : {
                                "type" : "string",
                                "enum" : [
                                    "value1",
                                    "value2"
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }

test data
 json data

  • case1 : If all elements are null, setting anyOf should result in an error
    "exampleX_2_0" : {




    },
  • case2 : If AnyOf is set and no value is found, no error occurs
    "exampleX_2_1" : {
        "dataA" : "data"



    },
    "exampleX_2_2" : {

        "dataB" : 1


    },
    "exampleX_2_3" : {
        "dataA" : "data",
        "dataB" : 1


    },
    "exampleX_2_4" : {


        "dataC" : true

    },
    "exampleX_2_8" : {



        "dataD" : "value1"
    },

Item names are identical within anyOf

    "Example1_3" : {
        "type" : "object",
        "allOf" : [
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "data1" : {
                                "type" : "string"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "data1" : {
                                "type" : "number"
                            }
                        }
                    }
                ]
            },
            {
                "type" : "object",
                "anyOf" : [
                    {
                        "type" : "object",
                        "properties" : {
                            "data2" : {
                                "type" : "boolean"
                            }
                        }
                    },
                    {
                        "type" : "object",
                        "properties" : {
                            "data2" : {
                                "type" : "string",
                                "enum" : [
                                    "value1",
                                    "value2"
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }

test data
 json data

  • case1 : If all elements are null, setting anyOf should result in an error
    "exampleX_3_0" : {




    },
  • case2 : If AnyOf is set and no value is found, no error occurs
    "exampleX_3_1" : {
        "data1" : "data"



    },
    "exampleX_3_2" : {

        "data1" : 1


    },
    "exampleX_3_3" : {
        "data1" : "data",
        "data1" : 1


    },
    "exampleX_3_4" : {


        "data2" : true

    },

from json-schema-validator.

justin-tay avatar justin-tay commented on June 26, 2024

I had a look but I don't see any issue with the behavior.

If there truly is an issue with oneOf or allOf you should use true and false to demonstrate this. Instead this looks like you don't really understand how the properties keyword works and you don't understand what happens when you have duplicate keys in JSON.

The properties keyword only does validation if the key exists, otherwise it will validate successfully. If you want an error if the key doesn't exist you need to use the required keyword.

Duplicate keys in JSON isn't recommended by the JSON spec and the general behavior is that the last key is taken and the earlier keys are ignored. This really doesn't have anything to do with this implementation or JSON Schema but with JSON itself.

If you for example type the following in your browser's javascript console

example = { data: 'data', data: 1}

you will get the following result

{data: 1}

from json-schema-validator.

ItouTerukazu avatar ItouTerukazu commented on June 26, 2024

@justin-tay
I apologize for my lack of understanding regarding the JSON Schema and JSON specifications. If I have any further questions about usage patterns, aside from the case of duplicate property names, I will be sure to ask again.

I am currently working on identifying any applicable cases.

Thank you very much for your polite and detailed response.

from json-schema-validator.

penguin2716 avatar penguin2716 commented on June 26, 2024

@justin-tay
I wrote a test pattern to validate the following objects as example. The object must have both age and user, and the user object must have either id or name.

{
  "age": 23,
  "user": {
    "id": 123,
  }
}
{
  "age": 23,
  "user": {
    "name": "john",
  }
}

The JSON schema is as follows.

{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "user": {
          "required": true,
          "oneOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": "number",
                  "required": true
                }
              }
            },
            {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "required": true
                }
              }
            }
          ]
        }
      }
    },
    {
      "type": "object",
      "properties": {
        "age": {
          "type": "number",
          "required": true
        }
      }
    }
  ]
}

The following is the test code. Some lines starting with //Assertions (commented out lines) cause the test fails, although this website tells the tests pass as exptected.

package com.networknt.schema;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.networknt.schema.SpecVersion.VersionFlag;

/**
 * Tests for nested applicators.
 */
public class NestedApplicatorTest {
    @Test
    void NestedAllOfOneOf() {
        String schemaData = "{\r\n"
            + "  \"allOf\": [\r\n"
            + "    {\r\n"
            + "      \"type\": \"object\",\r\n"
            + "      \"properties\": {\r\n"
            + "        \"user\": {\r\n"
            + "          \"required\": true,\r\n"
            + "          \"oneOf\": [\r\n"
            + "          	{\r\n"
            + "              \"type\": \"object\",\r\n"
            + "              \"properties\": {\r\n"
            + "                \"id\": {\r\n"
            + "                  \"type\": \"number\",\r\n"
            + "                  \"required\": true\r\n"
            + "                }\r\n"
            + "              }\r\n"
            + "            },\r\n"
            + "            {\r\n"
            + "              \"type\": \"object\",\r\n"
            + "              \"properties\": {\r\n"
            + "                \"name\": {\r\n"
            + "                  \"type\": \"string\",\r\n"
            + "                  \"required\": true\r\n"
            + "                }\r\n"
            + "              }\r\n"
            + "            }\r\n"
            + "          ]\r\n"
            + "        }\r\n"
            + "      }\r\n"
            + "    },\r\n"
            + "    {\r\n"
            + "      \"type\": \"object\",\r\n"
            + "      \"properties\": {\r\n"
            + "        \"age\": {\r\n"
            + "          \"type\": \"number\",\r\n"
            + "          \"required\": true\r\n"
            + "        }\r\n"
            + "      }\r\n"
            + "    }\r\n"
            + "  ]\r\n"
            + "}";

        JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData);

        /* Following two patterns should be valid, but the tests fail */
        //Assertions.assertTrue(schema.validate("{\"age\":23,\"user\":{\"id\":123}}", InputFormat.JSON).isEmpty());
        //Assertions.assertTrue(schema.validate("{\"age\":23,\"user\":{\"name\":\"john\"}}", InputFormat.JSON).isEmpty());

        /* Empty object should be invalid because of the allOf, but the test fails */
        //Assertions.assertFalse(schema.validate("{}", InputFormat.JSON).isEmpty());

        /* Following six patterns should be invalid (either age or user object is missing), but some tests fail */
        Assertions.assertFalse(schema.validate("{\"age\":\"old\"}", InputFormat.JSON).isEmpty());
        Assertions.assertFalse(schema.validate("{\"user\":{\"id\":123}}", InputFormat.JSON).isEmpty());
        Assertions.assertFalse(schema.validate("{\"user\":{\"name\":\"john\"}}", InputFormat.JSON).isEmpty());
        //Assertions.assertFalse(schema.validate("{\"age\":23}", InputFormat.JSON).isEmpty());
        //Assertions.assertFalse(schema.validate("{\"user\":{\"id\":\"abc\"}}", InputFormat.JSON).isEmpty());
        //Assertions.assertFalse(schema.validate("{\"user\":{\"name\":123}}", InputFormat.JSON).isEmpty());

        /* Following two patterns should be invalid (either id or name is invalid format), but the tests fail */
        //Assertions.assertFalse(schema.validate("{\"age\":23,\"user\":{\"id\":\"abc\"}}", InputFormat.JSON).isEmpty());
        //Assertions.assertFalse(schema.validate("{\"age\":23,\"user\":{\"name\":123}}", InputFormat.JSON).isEmpty());

        /* Following four patterns should be invalid (age must be a number), and the tests pass as expected */
        Assertions.assertFalse(schema.validate("{\"age\":\"old\",\"user\":{\"id\":123}}", InputFormat.JSON).isEmpty());
        Assertions.assertFalse(schema.validate("{\"age\":\"old\",\"user\":{\"id\":\"abc\"}}", InputFormat.JSON).isEmpty());
        Assertions.assertFalse(schema.validate("{\"age\":\"old\",\"user\":{\"name\":\"john\"}}", InputFormat.JSON).isEmpty());
        Assertions.assertFalse(schema.validate("{\"age\":\"old\",\"user\":{\"name\":123}}", InputFormat.JSON).isEmpty());
    }
}

Is the test code above seems reasonable? I'm not so familier with neither Java nor JSON Schema, but I hope the example helps our understanding or potential issues if any.

from json-schema-validator.

Yuutakasan avatar Yuutakasan commented on June 26, 2024

@justin-tay I think the cause was our lack of understanding of Json and Json-schema. Thanks to your excellent support, our team was able to properly understand the documentation. Thank you very much.
We are using it as a validator for the OpenAPI Spec, and since Json-schema is a good specification, we want to use it. However, if the underlying Json-schema specification is unclear, it will be troublesome for both the development side and the user side.
Anyway, your help was truly appreciated. Thank you very much.

from json-schema-validator.

penguin2716 avatar penguin2716 commented on June 26, 2024

@justin-tay
I checked some additional test cases with combinations of allOf and oneOf, and what we had to do to pass the test was to fix the JSON schemas to the correct format in all cases.
Some GUI editors for the OpenAPI spec provide a user interface for us to define schemas using allOf / oneOf / anyOf. Since the UI simply shows the combined schemas, I misunderstood what those combined schemas mean and how the validator works.
Thank you very much for your quick and detailed explanation.

from json-schema-validator.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.