ref for enum?

2,880 views
Skip to first unread message

Dan

unread,
Apr 16, 2012, 2:26:08 PM4/16/12
to JSON Schema
Hi,

I need to validate that a property in an object only contains values
from a list specified in an array earlier in that object. Any ideas on
why the schema below isn't working?

Thanks,
Dan

Valid Data:
{
"ruleTargets": ["one", "two"],
"rule": {"target": "one"}
}

Invalid Data
{
"ruleTargets": ["one", "two"],
"rule": {"target": "three"}
}

Schema
{
"type": "object",
"properties": {
"ruleTargets": {
"type": "array",
"items": { "type": "string" }
},
"rule": {
"type": "object",
"properties": {
"target": {
"type": "string",
"enum": {"$ref": "#ruleTargets"}
}
}
}
}
}

Francis Galiegue

unread,
Apr 17, 2012, 5:29:15 AM4/17/12
to json-...@googlegroups.com
On Mon, Apr 16, 2012 at 20:26, Dan <dan.go...@gmail.com> wrote:
> Hi,
>
> I need to validate that a property in an object only contains values
> from a list specified in an array earlier in that object.

Unfortunately, you cannot do that. The JSON specification does not
specify any key order, therefore JSON APIs offer no guarantee in this
regard either. And consider the following (valid) JSON fragment:

{
"key1": "value1",
"key1": "value2"
}

You cannot know in advance what the value of "key1" will be.

--
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)

Francis Galiegue

unread,
Apr 17, 2012, 7:39:28 AM4/17/12
to json-...@googlegroups.com
On Tue, Apr 17, 2012 at 11:29, Francis Galiegue <fgal...@gmail.com> wrote:
[...]

>
> {
>    "key1": "value1",
>    "key1": "value2"
> }
>
> You cannot know in advance what the value of "key1" will be.
>

To make matters even worse, I recall trying at some point a JSON API
written in Java which, in such an event, would return an _array_ of
the different values for the key... Which is evidently bizarre, but
_does not_ contradict the JSON specification either. Bah.

Anyway, if you do want to do this and use server-side validation, my
API can do what you request: you just have to write your own keyword
validators, and you can do that.

dan.go...@gmail.com

unread,
Apr 17, 2012, 5:09:19 PM4/17/12
to json-...@googlegroups.com
Thanks Francis - that's disappointing, but makes sense.  

On Tuesday, April 17, 2012 5:29:15 AM UTC-4, fge wrote:

N. Morse

unread,
Apr 17, 2012, 5:34:37 PM4/17/12
to json-...@googlegroups.com
Wait a minute, I think that your original question could work, I mean,
you are close, because if I hard code in

["one", "two"]
for your reference:
{"$ref": "#ruleTargets"}
then all is fine (yes: the "Valid Data" example is valid, and the
"Invalid Data" is invalid).
The problem is just something to do with how the $ref is evaluated
into an array of schemas.
Have you tried a full path to the JSON URI, (i.e. {"$ref":
"http://domain.com/path/to/valid_data.json#/ruleTargets"} )?

> --
> You received this message because you are subscribed to the Google Groups
> "JSON Schema" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/json-schema/-/uEoC1hzmxUUJ.
>
> To post to this group, send email to json-...@googlegroups.com.
> To unsubscribe from this group, send email to
> json-schema...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/json-schema?hl=en.

Francis Galiegue

unread,
Apr 18, 2012, 3:09:41 AM4/18/12
to json-...@googlegroups.com
On Tue, Apr 17, 2012 at 23:34, N. Morse <nmo...@academiccatalog.com> wrote:
> Wait a minute, I think that your original question could work, I mean,
> you are close, because if I hard code in
>
>  ["one", "two"]
> for your reference:
> {"$ref": "#ruleTargets"}
> then all is fine (yes: the "Valid Data" example is valid, and the
> "Invalid Data" is invalid).
> The problem is just something to do with how the $ref is evaluated
> into an array of schemas.

The problem to start with is that enum takes an array as an argument
(possibly empty BTW), and each element in the enum is not a schema,
but a JSON document which the value must match. For instance:

{
"enum": [ { "an": "object" }, null, 2.32, { "$ref": "#" }, [ 1, 2, 3 ] ]
}

If you actually want a value to match one schema among many, you have
to use the "type" keyword:

{
"type": [
{ // schema 1 here },
{ // schema 2 here },
// etc
]

N. Morse

unread,
Apr 18, 2012, 9:35:18 AM4/18/12
to json-...@googlegroups.com
Sorry I miss-spoke, I meant to say and array of "elements", not "schema"
But it I understand the original question "ref for enum", it boils down to:
"Can {"$ref": "#ruleTargets"} refer to an element in an arbitrary JSON
document?"
Because if it can, then the original example in this thread should work.
--Nate

> --
> You received this message because you are subscribed to the Google Groups "JSON Schema" group.

Francis Galiegue

unread,
Apr 18, 2012, 9:48:54 AM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 15:35, N. Morse <nmo...@academiccatalog.com> wrote:
> Sorry I miss-spoke, I meant to say and array of "elements", not "schema"
> But it I understand the original question "ref for enum", it boils down to:
> "Can {"$ref": "#ruleTargets"} refer to an element in an arbitrary JSON
> document?"
> Because if it can, then the original example in this thread should work.


OK, so: yes, "$ref" can refer to an arbitraty JSON document (even a
non existing one for that matter). But no, the example won't work.
This is because the enum keyword itself does not work this way.
The contents of enum is a JSON array:

[ d1, d2, .... ]

where d1, d2, etc are themselves JSON documents -- documents, _not_ schemas.

Right now, "$ref" is really meant to only refer to schemas within
schemas -- which means JSON documents pointed to by "$ref" _must_ be
valid schemas as well. Extending its role the way you describe would
require modifying the spec a great deal, as this would not only affect
the enum keyword. In fact, I suspect this cannot be done but cannot
give an example as to why at the moment.

N. Morse

unread,
Apr 18, 2012, 1:03:54 PM4/18/12
to json-...@googlegroups.com
Thanks Francis, I appreciate your explanation, although it is
disappointing that $ref cannot substitute in the JSON array (as
required by the enum:) right now.
I accept that it cannot be done (now! or ever?), but
If in time, you do find a reason why this cannot (ever) be done, I
would be interested in some (counter) example. much thanks,
--Nate Morse

Francis Galiegue

unread,
Apr 18, 2012, 6:52:50 PM4/18/12
to json-...@googlegroups.com
On Wed, Apr 18, 2012 at 19:03, N. Morse <nmo...@academiccatalog.com> wrote:
> Thanks Francis, I appreciate your explanation, although it is
> disappointing that $ref cannot substitute in the JSON array (as
> required by the enum:) right now.
> I accept that it cannot be done (now! or ever?), but
> If in time, you do find a reason why this cannot (ever) be done, I
> would be interested in some (counter) example. much thanks,
> --Nate Morse
>

Well, in fact, I don't see one. After all, the current spec defines
$ref as a special case for a JSON Reference
(http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-02).

Your proposal would make $ref a fully fledged JSON Reference. I think
this is a good idea for draft v4. Comments?

Francis Galiegue

unread,
Apr 18, 2012, 6:54:39 PM4/18/12
to json-...@googlegroups.com
On Thu, Apr 19, 2012 at 00:52, Francis Galiegue <fgal...@gmail.com> wrote:
>
> Well, in fact, I don't see one.
>

OK, I do see one. URIs are supposed to be resolved relative to the
current schema's URI. As such, "#whatever" will try to look for
"#whatever" in the schema, _not_ the JSON document being validated...

N. Morse

unread,
Apr 19, 2012, 7:37:25 AM4/19/12
to json-...@googlegroups.com

Ok, You are saying that local references are within the schema itself, so "local reference" will not work for Dan's example.  So, if he references another document#/value like
{ "$ref": "http://example.com/example.json#/foo/bar" }
... Then, there is no problem that I can see.
--Nate

Francis Galiegue

unread,
Apr 19, 2012, 7:45:53 AM4/19/12
to json-...@googlegroups.com
On Thu, Apr 19, 2012 at 13:37, N. Morse <nmo...@academiccatalog.com> wrote:
> Ok, You are saying that local references are within the schema itself, so
> "local reference" will not work for Dan's example.  So, if he references
> another document#/value like
> { "$ref": "http://example.com/example.json#/foo/bar" }
> ... Then, there is no problem that I can see.

_IF_ "$ref" is really meant to be a JSON reference. The wording in the
current specification (as far as I read it) doesn't really say that,
and therefore it cannot be really counted upon...

Another trick was mentioned on this list by Flavien Volken, which is
to use external validation services via $ref:

{
"$ref": "http://some.processor/somewhere?with=params"
}

which is a very pretty hack. If you have this, you can make a service
return a schema, say, like this:

{
"enum": [ "list", "of", "values" ]
}

which would pretty much have the same effect.

Reply all
Reply to author
Forward
0 new messages