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

add property to object with additionalProperties: false from switch #205

Closed
mbroadst opened this issue Jun 3, 2016 · 11 comments
Closed
Labels

Comments

@mbroadst
Copy link
Contributor

mbroadst commented Jun 3, 2016

should this be possible:

{
  type: 'object',
  properties: {
    foo: { type: 'array', minItems: 2 },
    bar: { type: 'string' }
  },
  additionalProperties: false,
  required: [ 'foo', 'bar' ],
  switch: [{
    if: { properties: { bar: { constant: 'testing } } },
    then: {
      properties: { baz: { type: 'string' } },
      required: [ 'foo', 'bar', 'baz' ]
    }
  }]
}

It seems unclear from the documentation, but shouldn't I technically be able to even set additionalProperties: true in the switch's then?

@epoberezkin
Copy link
Member

epoberezkin commented Jun 3, 2016

additionalProperties are scoped to the current schema, they don't have global visibility...

In this case it means that additionalProperties will fail validation if any property in addition to foo and bar is present. You cannot extend it by declaring properties in another schema object, they should be declared in the same schema object. That's by the spec.

You need:

{
  type: 'object',
  properties: {
    foo: { type: 'array', minItems: 2 },
    bar: { type: 'string' }
    baz: { type: 'string' },
  },
  additionalProperties: false,
  required: [ 'foo', 'bar' ],
  switch: [
    {
      if: { properties: { bar: { constant: 'testing' } } },
      then: {
        required: [ 'baz' ]
      }
    },
    {
      then: { not: { required: ['baz'] } }
    }
  ]
}

@epoberezkin
Copy link
Member

See #129, #134, #140

@epoberezkin
Copy link
Member

epoberezkin commented Jun 3, 2016

And you don't need v5 switch for that, oneOf will work too.

@epoberezkin
Copy link
Member

epoberezkin commented Jun 3, 2016

Maybe it will all make more sense if you think about it in this way: JSON Schema may seem like it is about declaring what is allowed, but it is not. JSON Schema is about imposing restrictions. So you can easily extend the restrictions by adding them to any schema (like in the case with required above, where you don't need to repeat properties required in another schema object). But you cannot reduce the restriction by adding something to another schema object (like adding property declaration to another schema in your example). To reduce the restriction you need to modify the schema that imposed the restriction (or to use anyOf/oneOf). Not sure if I made it any clearer to be honest...

@mbroadst
Copy link
Contributor Author

mbroadst commented Jun 3, 2016

@epoberezkin no you've been quite clear, I think it was I who was not so clear in the initial case. What I'm looking for here is to explicitly disallow baz in case the value of bar === testing. I haven't been able to sort out how to get that working yet, other than providing whole separate schemas and using oneOf

@epoberezkin
Copy link
Member

you can use not with required as in my example to prohibit proberty

@mbroadst
Copy link
Contributor Author

mbroadst commented Jun 3, 2016

oh really? I had thought that would just remove it from the required list, that's a bit of a semantic misnomer I'd say as the negation of requirement isn't necessarily prohibition 😄

Totally works, thank you very much for your help

@mbroadst mbroadst closed this as completed Jun 3, 2016
@epoberezkin
Copy link
Member

not negates validation result. not passes when schema inside fails. required fails when property is absent.

@epoberezkin
Copy link
Member

But semantically it is funny indeed

@mbroadst
Copy link
Contributor Author

mbroadst commented Jun 3, 2016

it might make sense to suggest an alias present for required (to the json-schema spec maintainers that is). This is far more readable imho:

then: { not: { present: [ 'baz' ] } }

@epoberezkin
Copy link
Member

You don't have to wait for the standard change :)

ajv.addKeyword('present', {
  macro: (schema) => ({ required: schema });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants