Closed qu1ck closed 2 years ago
Yes, that's possible. Of course I'd say.
What have you tried to achieve it? (It's a little bit off-topic here, without giving you the solution, I'd prefer you to find out yourself)
I haven't tried anything as in writing code, I just looked at the api in json-schema.hpp and I see no way to specify anywhere that validation should happen against schema #/definitions/A
.
I only see API to set root schema and to validate json object against that root schema.
If A
didn't reference B
then I could set root schema as root["definitions"]["A"]
but then $ref
will not be able to resolve #/definitions/B
.
What am I missing?
Oh, I see. I'm assuming you're just starting with schema?
There is nothing to be done on the C++-API of the validator for what you want to do. Everything has to be defined in the schema. The validator just "compiles" the schema and then uses it as is to validate instances. So, in your schema from above you define the root-schema as integer, so effectively the part in the definitions can't be referenced inside the same schema.
If you use root-schema of object type, then you can:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"A": {
"type": "object",
"properties": {
"b": {
"$ref": "#/definitions/B"
}
}
},
"B": {
"type": "integer"
}
},
"properties": {
"propname": { "$ref": "#/definitions/B"}
}
}
Would validate an instance like this
{
"propname": 1
}
Yeah, sorry if my example was a bit too simplistic, I used integer to just show that what root schema describes itself is not important.
The actual problem I want to solve looks like this (only hierarchy of definitions described)
repository
+package
+packageversion
+resource
And both repository
and packageversion
have resource
fields and package
has array of packageversion
fields. And of course repository
has array of package
fields.
Now sometimes I have a json object of package that I want to validate and I don't have a whole repository. Can I do that using this common schema or do I have to break it up into several schemas and potentially redefine resource
?
In my mind the API for doing that would look something like validator.set_root_schema(schema)
and then validator.validate(object, "#/definitions/package")
to specify that the object should conform to package
definition within the schema and not the whole schema.
OK, I see, sorry to have taken you as a newbie.
You'd be surprised, or maybe not, but there is a request which resembles yours quite a bit: #135
There, the idea is to do one parsing of all schemas and sub-schemas and then create linked validator-instances based on a json-paths (IIRC). (Additionally dynamic additions of new sub-schemas without reparsing everything again)
That would solve your problem as well, no?
json_validator validator(loader);
validator.set_root_schema(schema);
auto &sub_validator = validator.get_some_good_name("#/definitions/package")
sub_validator.validate(package_instance);
How would you know which json-path to pick based on the instance-type?
Would you allow sub-schema breakouts when a reference in your selection sub-schema has a reference to a schema outside it's scope? Because in my idea it would work.
Adding the validator.get_some_good_name("#/definitions/package")
-method would be more complicated than implementing your validator.validate(object, "#/definitions/package")
idea.
It is actually already possible with just one minor addition to the validate call - which is the initial json-uri of where you want to start.
But still, it would breakout the scope if an upper-lever reference appears.
Diff looks good, solves my problem nicely.
There, the idea is to do one parsing of all schemas and sub-schemas and then create linked validator-instances based on a json-paths (IIRC). (Additionally dynamic additions of new sub-schemas without reparsing everything again)
That would work too but I can see that it would be harder to implement.
How would you know which json-path to pick based on the instance-type?
I think it's reasonable to require the path to be provided either explicitly in code or in object itself using "$schema": "<schemauri>#<pathtosubdefinition>"
. But maybe I'm misunderstanding the question?
Would you be able to try out my changes to see whether it's OK?
Keeping a list of entrypoints in each sub-part of a program using a schema with multiple direct uses of "sub-schema" sounds reasonable.
Before merging this feature, we'd need more tests. Especially some with cross-file references, to see whether this makes sense. (I strongly thinks it will work out nicely).
Yes, I can try it out but my usage will be relatively simple like the test you already added. No multi file schemas with cross references. I'll be back with some links in a day or two.
Sorry for delay, needed to get my feature in a somewhat workable state. TLDR: it works.
Here is the schema (still work in progress, had to rearrange it a bit for unrelated reasons): https://gitlab.com/qu1ck/kicad/-/blob/pcm/pcm/schemas/pcm.v1.schema.json
And here I'm validating this object: https://gitlab.com/qu1ck/kicad-pcm-repository/-/raw/master/repository.json against a sub definition of the schema: https://gitlab.com/qu1ck/kicad/-/blob/f98df2a4264cab8dbe1e13261e88fc46165223c1/pcm/pcm.cpp#L110
Say there is a schema with sub definitions A and B while A also references B
Is there a way to validate that an object conforms to schema A?