RicoSuter / NJsonSchema

JSON Schema reader, generator and validator for .NET
http://NJsonSchema.org
MIT License
1.4k stars 535 forks source link

JsconSchema doesn`t validate required property inside anyOf #325

Open dynamicmoodz opened 7 years ago

dynamicmoodz commented 7 years ago

I have this json schema which is being used in the code below. { "definitions": { "Test": { "id": "Jsonschemas/", "type": "object", "properties": { "url": { "type": "string" }, "canceledOnDate": { "type": "string" }, "address": { "$ref": "address.json#/definitions/address" }, "coordinates": { "$ref": "coordinates.json#/definitions/coordinates" } }, "additionalProperties": false, "required": ["canceledOnDate" ], "anyOf": [ { "required": [ "address" ] }, { "required": [ "coordinates" ] } ] } } }

I have this C# code which is using JsonSchema4.

JsonSchema4 schema = new JsonSchema4();
schema = await JsonSchema4.FromFileAsync(Path.Combine(HttpContext.Current.Server.MapPath("~"), @"JsonSchema/Test.json")); schema.Validate(actualJsonData);

I am expecting that based on the schema if I dont provide either address or cocrdinates, the Validate method should return me error. But it doesn`t validate the required field in anyOf at all. The validation always passes even if address and coordinates both are not provided.

Is it not supported with JsonSchema4? I am looking for help to fix this problem or a work around to fix this issue.

RicoSuter commented 7 years ago

I think this is because you only defined the properties in "required" but didn't declare them in "properties"

RicoSuter commented 7 years ago

Should this be allowed?

dynamicmoodz commented 7 years ago

I did declare address and coordinates in actual properties and they are defined as required. It is a valid Json schema. I have ran it on other validators and it works just fine other then this library.

RicoSuter commented 7 years ago

Define the properties here

{ "required": [ "address" ] },

Like

{ "required": [ "address" ], "properties": { "address": {} } },
dynamicmoodz commented 7 years ago

Do you mean the schema should be defined like this? I have ran the following schema and it seems to work. I haven`t tested all other scenarios. Do i have to define address and coordinates both as part of required properties and other properties as defined below?

{
  "definitions": {
    "warrant": {
      "id": "Jsonschemas/",
      "type": "object",
      "properties": {
        "url": {
          "type": "string"
        },
        "canceledOnDate": {
          "type": "string"
        },
        "expiresOnDate": {
          "type": "string"
        },
        "servedOnDate": {
          "type": "string"
        },
        "name": {
          "$ref": "name.json#/definitions/name"
        },
        "address": {
          "$ref": "address.json#/definitions/address"
        },
        "coordinates": {
          "$ref": "coordinates.json#/definitions/coordinates"
        },
        "offenses": {
          "type": "array",
          "items": {
            "$ref": "offense.json#/definitions/offense"
          }
        }
      },
      "additionalProperties": false,
      "required": [
        "canceledOnDate",
        "expiresOnDate",
        "servedOnDate",
        "name",
        "offenses"
      ],
      "anyOf": [
        {
          "required": [ "address" ],
          "properties": {
            "address": {
              "$ref": "address.json#/definitions/address"
            }
          }
        },
        {
          "required": [ "coordinates" ],
          "properties": {
            "coordinates": {
              "$ref": "coordinates.json#/definitions/coordinates"
            }
          }
        }
      ]
    }
  }
}
dynamicmoodz commented 7 years ago

However my original schema works with other Json schema validators.

{
"type": "object",
"required": [
"accountNumber",
"parcelNumber"
],
"anyOf": [
{"required" : ["address"]},
{"required" : ["coordinates"]}
],
"properties": {
"id": {
"type": "string"
},
"accountNumber": {
"type": "string"
},
"parcelNumber": {
"type": "string"
},
"propertyType": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"addressString": {
"type": "string"
},
"addressType": {
"enum": [
"residential",
"business"
]
}
},
"required": [
"addressString"
]
},
"coordinates": {
"type": "object",
"properties": {
"latitude": {
"type": "number"
},
"longitude": {
"type": "number"
},
"projection": {
"type": "string"
}
},
"required": [
"latitude",
"longitude",
"projection"
]
}
}
}

Here is the data to prove this.

{
"accountNumber": "test",
"parcelNumber": "testt",
"address": {
"addressString": "Avenue Q"
},
"coordinates": {
"latitude": 42,
"longitude":42,
"projection": ""
}
}

If you remove address and coordinates both from the data, you will receive error that one of it is required.

You can test it out here. http://www.jsonschemavalidator.net/

My questions is why the NJsonSchema doesn`t supports it? This is very clean approach rather then defining address and coordinates both as part of required properties and other properties?

Please let me know if my ask is not clear.

thakgit commented 7 years ago

I also have same problem I am using OneOf and required doesnt work at all, though I am using FromData to load the schema, should it matter?

dynamicmoodz commented 7 years ago

I dont think its FromData. I see same problem with FromFile.

However, the work around is to define the properties in the required field as i have in my example above. That should work for now.

thakgit commented 7 years ago

Thanks a lot , that works!

RicoSuter commented 7 years ago

Will rename FromData to FromSampleJson..

jarzantarzan commented 6 years ago

Has this issue been resolved? I have the following schema (truncated for brevity):

{ "type": "object", "properties": { "bContinuousStay": { "type": "boolean" }, "dStayStartDate": { "type": "string" }, "dStayEndDate": { "type": "string" } }, "required": [ "bContinuousStay" ], "anyOf": [ { "properties": { "bContinuousStay": { "enum": [ true ] } } }, { "properties": { "bContinuousStay": { "enum": [ false ] } }, "required": [ "dStayStartDate", "dStayEndDate" ] } ] }

It validates fine in online validators but does not in NJsonSchema. If I defined the "dStayStartDate" and "dStayEndDate" properties in the main "required" array it kills the whole purpose of anyOf (they must always be present then).

Any workarounds are accepted as I have a deadline and a lot of similar scenarios to catch :)