json-schema icon indicating copy to clipboard operation
json-schema copied to clipboard

draft 4 schema doesn't require

Open jdarling opened this issue 11 years ago • 8 comments

Taking the sample schema from json-schema.org directly:

var schema = {
    "title": "Example Schema",
    "type": "object",
    "properties": {
        "firstName": {
            "type": "string"
        },
        "lastName": {
            "type": "string"
        },
        "age": {
            "description": "Age in years",
            "type": "integer",
            "minimum": 0
        }
    },
    "required": ["firstName", "lastName"]
};

And calling validate on an invalid object, will result in a return saying its valid:

var js = require('json-schema');
console.log(js.validate({firstName: 'Test'}, schema).errors);

Output is an empty array: []

jdarling avatar Mar 29 '13 17:03 jdarling

Just for anyone else who wants to get around this as well, here is a quick fix option that will set the required flag on all properties based upon the required root object array:

var enhanceRequired = function(root){
  var required;
  if(typeof(root)!=='object'){
    return;
  }
  if((root.required instanceof Array)||(root.required&&root.required.length)){
    required = Array.prototype.slice.call(root.required);
  }else{
    required = [];
  }
  if(root.properties){
    var keys = Object.keys(root.properties), value;
    keys.forEach(function(key){
      value = root.properties[key];
      enhanceRequired(value);
      if(required.indexOf(key)>-1){
        value.required = true;
      }
    });
  }
}
enhanceRequired(schema);

jdarling avatar Mar 29 '13 17:03 jdarling

Why was "required" changed from an object property to be a separate array on the schema in v4? It's a horrible change. It's much simpler and cleanly encapsulated in the v3 spec.

krisnye avatar Feb 25 '14 18:02 krisnye

krisnye, in Version 4, the key "required" has been removed from inside the property because in some cases you need to say that a "foo" property is required even if it is not formally declared as property of the schema. An object can be set as "AdditionalProperties = true" and require the "foo" property, which is not declared.

jemanzo avatar Mar 07 '14 21:03 jemanzo

That is even worse. Why don't you just declare the foo property if you need it required?

By putting it into the required property you are essentially making a mini-declaration about that property. Now instead of having a single place to look for property declarations you have two potential places.

krisnye avatar Mar 10 '14 15:03 krisnye

The fact of not wanting to declare the property "foo" is just one example among many. Let's assume you have a "customer" object, and inside it you have the customer data and various addresses like "commercial, residential, contact...". In this case you will declare only one address scheme on "definitions" so all point to it using "$ref", e.g. "{commercial:{$ref:"/definitions/address"}}". If you say "/definitions/address" is required using a "required" key within it, all addresses properties that point to it would be required, but in this case you just want the "residential" address to be required, not all.

It makes more sense to think "I'm an object that requires ["X","Y","Z"] properties"(like v4) than "I'm a required property of any object that i'm inside"(like it was in v3).

jemanzo avatar Mar 11 '14 05:03 jemanzo

That makes sense, but why not be able to override referenced schemas.

{commercial:{$ref:"/definitions/address", required: true}}

or

{commercial:{$ref:"/definitions/address", required: false}}

krisnye avatar Mar 11 '14 23:03 krisnye

You can't do that. The purpose of "$ref" is to replace the current value by the referenced value, so, the atribute "required" would be ignored.

The key "$ref" is based on JSON Reference (http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) where it says: "Any members other than "$ref" in a JSON Reference object SHALL be ignored.".

jemanzo avatar Mar 12 '14 06:03 jemanzo

I know, but it would be nice. Any properties specified on the object containing the ref would define or override existing properties in the referenced schema. It should be functionally equivalent to copying the referenced schema and applying a JSON-merge-patch containing the other properties to it.

krisnye avatar Mar 12 '14 17:03 krisnye