Extend a schema by removing properties - possible?

153 views
Skip to first unread message

Andrei Neculau

unread,
Apr 18, 2012, 3:25:42 AM4/18/12
to json-...@googlegroups.com
Can you extend a model and declare a property as "undefined" ?
Otherwise, I guess one has to declare a subset schema - the common denominator.

Francis Galiegue

unread,
Apr 18, 2012, 3:30:08 AM4/18/12
to json-...@googlegroups.com

Care to give an example of what you want to achieve? You cannot
declare a property as "undefined" currently, you can only specify that
you don't want any additional properties than the ones you declare in
"properties" (by name) or "patternProperties" (by regex matching).

--
Francis Galiegue, fgal...@gmail.com
"It seems obvious [...] that at least some 'business intelligence'
tools invest so much intelligence on the business side that they have
nothing left for generating SQL queries" (Stéphane Faroult, in "The
Art of SQL", ISBN 0-596-00894-5)

Andrei Neculau

unread,
Apr 18, 2012, 3:45:02 AM4/18/12
to json-...@googlegroups.com
{
 "id": "address",
 "properties": {
  "first_name": {}
  "last_name": {},
  "street": {}
 }
}

{
 "id": "address2",
 "extends": "address",
 "properties": {
  "first_name": {
   "type": "undefined"
  },
  "last_name": {
   "type": "undefined"
  },
  "full_name": {}
 }
}

If you create an instance of address2, it should not have any first_name, last_name properties, just full_name and street

Francis Galiegue

unread,
Apr 18, 2012, 3:55:04 AM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 09:45, Andrei Neculau <andrei....@gmail.com> wrote:
> {
>  "id": "address",
>  "properties": {
>   "first_name": {}
>   "last_name": {},
>   "street": {}
>  }
> }
>
> {
>  "id": "address2",
>  "extends": "address",
>  "properties": {
>   "first_name": {
>    "type": "undefined"
>   },
>   "last_name": {
>    "type": "undefined"
>   },
>   "full_name": {}
>  }
> }
>
> If you create an instance of address2, it should not have any first_name,
> last_name properties, just full_name and street
>

And no other, right?

In this case, you can do that:

{
"extends" : { "$ref": "uri://to/address/schema" },
"properties": {
"full_name": {},
"street": {}
},
"additionalProperties": false
}

It means that the schemas for the full_name and street properties must
be declared in the address schema. But be careful about IDs: "address"
doesn't sound valid -- how do you, well, address it from outside the
schema?

Andrei Neculau

unread,
Apr 18, 2012, 4:33:19 AM4/18/12
to json-...@googlegroups.com
Beyond the ID, extends discussion (I've just thrown some quick boilerplate, but thanks for pointing that out for other readers/learners!),
I think I am having a different understanding of additionalProperties.
I haven't use it so far, but I take its definition as = this schema is not to be extended.

Otherwise your structure doesn't make sense to me:
- you extend address2 with first_name, last_name, street (street you actually overwrite with a new definition)
- you say "no additional properties" other than full_name and street

but how is that different from removing the "extends" altogether? since full_name and street are fully defined?

I'm thinking that the solution to my problem is just cherry-picking, rather than extending. Example
{
 "properties": {
  "full_name": {}
  "street": {
   "$ref": "....../address#street
  }
 }
}
although as I see it, this means adding an "id" attribute to all properties. Or use JSON Pointer like "$ref": "..../address#/properties/street"

Am I wrong to think that?

Thanks, Francis.

Francis Galiegue

unread,
Apr 18, 2012, 4:53:50 AM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 10:33, Andrei Neculau <andrei....@gmail.com> wrote:
> Beyond the ID, extends discussion (I've just thrown some quick boilerplate,
> but thanks for pointing that out for other readers/learners!),
> I think I am having a different understanding of additionalProperties.
> I haven't use it so far, but I take its definition as = this schema is not
> to be extended.
>
> Otherwise your structure doesn't make sense to me:
> - you extend address2 with first_name, last_name, street (street you
> actually overwrite with a new definition)

No, I don't. Extending a schema does _not_ mean that you replace the
schema for a given property, but that you _add_ another schema which
the property must obey. When s2 extends s1, it means all constraints
of s1 and s2 must be obeyed for a JSON instance to be considered
valid.

Here, both "full_name" and "street" must obey:

* the schema defined by "properties" in the address schema; and
* the schema defined by "properties" in address2, which is empty.

And an empty schema ({}) can match anything. So, this is really adding
a "noop" constraint.

> - you say "no additional properties" other than full_name and street
>

Which is what you wanted to achieve, right?

> but how is that different from removing the "extends" altogether? since
> full_name and street are fully defined?
>

It is different in the sense that by extending the schema, I added a
constraint, which the original schema doesn't have. Mainly, the
additionalProperties constraint.

I guess I somewhat misunderstand your questions though.

> I'm thinking that the solution to my problem is just cherry-picking, rather
> than extending. Example
> {
>  "properties": {
>   "full_name": {}
>   "street": {
>    "$ref": "....../address#street
>   }
>  }
> }
> although as I see it, this means adding an "id" attribute to all properties.
> Or use JSON Pointer like "$ref": "..../address#/properties/street"
>
> Am I wrong to think that?
>

That would be another solution, yes, but as you can see I chose to
extend the schema instead. The original schema already defines that
the instance should be an object and describes its properties,
"full_name" and "street" included. (of which, BTW, none is required --
that is another tricky part to get right in your case).

> Thanks, Francis.

No problem !

Francis Galiegue

unread,
Apr 18, 2012, 4:54:34 AM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 10:53, Francis Galiegue <fgal...@gmail.com> wrote:
[...]

>
> No, I don't. Extending a schema does _not_ mean that you replace the
> schema for a given property, but that you _add_ another schema which
> the property must obey. When s2 extends s1, it means all constraints
> of s1 and s2 must be obeyed for a JSON instance to be considered
> valid.
>

I really meant "instance", not "property" in the above.

Francis Galiegue

unread,
Apr 18, 2012, 5:02:23 AM4/18/12
to json-...@googlegroups.com
Oh, and BTW:

On Wed, Apr 18, 2012 at 10:33, Andrei Neculau <andrei....@gmail.com> wrote:

[...]


>
> I'm thinking that the solution to my problem is just cherry-picking, rather
> than extending. Example
> {
>  "properties": {
>   "full_name": {}
>   "street": {
>    "$ref": "....../address#street
>   }
>  }
> }

You do not specify the type here! As by default the value of "type" is
"any", it means that this schema will consider _all_ JSON instances
other than objects as valid.

More generally, when you encounter a keyword in a schema, it only ever
applies to some instances. This schema, for instance:

{
"minimum": -1
}

will only ever add a constraint to instances of type "number" and "integer".

Francis Galiegue

unread,
Apr 18, 2012, 9:32:50 AM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 10:33, Andrei Neculau <andrei....@gmail.com> wrote:
[...]
> I think I am having a different understanding of additionalProperties.
> I haven't use it so far, but I take its definition as = this schema is not
> to be extended.
>

OK, that's not quite true. I'll try to explain fully what
additionalProperties means:

* it has two valid values: either a JSON boolean (so, literally, false
or true), or a schema. An empty schema is the equivalent of boolean
value true;
* "additionalProperties" is to be taken into consideration _if and
only if_ a property:
* has no matching entry in "properties"; and
* does not obey any regex in "patternProperties".
* when "additionalProperties" is false, this means that no other
property than the ones defined in "properties" or "patternProperties"
should exist in the instance;
* the default value for "additionalProperties", if not present in the
schema, is the empty schema (or boolean value true, which has pretty
much the same effect).

So, for instance, this:

{
"type": "object",
"properties": {
"p": { //whatever schema here }
},
"additionalProperties": false
}

pretty much restricts an instance to be an object and only have one
key, namely "p". As "additionalProperties" is set to false here, it
means no other property than "p" can appear in an instance
("patternProperties" is not specified either).

On the other hand, if "additionalProperties" was _not_ specified
above, it would mean that if a key named "p" was present in the object
instance, it'd have to obey the schema, regardless of other keys
defined in the object (other keys would have to obey the empty schema,
which validates each and every JSON document).

I can explain some more on request. The relationship between
"properties", "patternProperties" and "additionalProperties" is not a
simple one...

Andrei Neculau

unread,
Apr 19, 2012, 2:40:19 AM4/19/12
to json-...@googlegroups.com
Thank you for your time and patience, Francis.
I understand now the reasoning, and also the draft's phrasing.

Xample

unread,
Apr 20, 2012, 3:14:59 AM4/20/12
to json-...@googlegroups.com
well in short : the "extends" property should be considered as an "include" one. It does not shadow any other properties as a real "extends" should do.
That is why I have suggested many times to rename it to "include" and to complete the "extends" so that it may inherit from many sub schemas the proper way.
Reply all
Reply to author
Forward
0 new messages