Closed kentcb closed 4 years ago
In your example, both definitions have an $id
of #first
. This may be a typo, but it'll definitely not work that way. I'll assume that you mean #second
for the second definition, as indicated by your question.
I'm going to file this under "use cases I never considered". I'm guessing that you're actually loading a schema from disk and you want a one of its subschemas.
Do you have control over that schema file? If so, I'd suggest breaking it into multiple schemas rather than loading one and trying to pick out a subschema.
Schema 1
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"first": {
"$id": "#first",
"properties": {
"foo": {
"type": "string"
}
},
"required": [
"foo"
]
}
},
"type": "object",
"$ref": "file:///c:\\schemas\\second.json" // or whatever
}
Schema 2
{
"$id": "#first",
"properties": {
"bar": {
"type": "string"
}
},
"required": [
"bar"
]
}
If that's not possible then you're pretty much better off doing what you're doing, though getting to the definitions can be a little simpler by using the extension method:
var second = schema.Definitions()["second"];
I'd avoid the ResolveSubschema()
method. That's designed for keywords to be able to resolve references. The only reason it's public is because the library is designed so that users can define their own keywords and may need this functionality.
Thanks for the quick response.
Yeah, that was a typo sorry. Also, whilst my hack works in the case of my simple repro above, it falls apart when the sub-schema itself uses $ref
as in this example:
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"something": {
"$id": "#something",
"properties": {
"id": {
"$ref": "#uuid"
}
},
"required": [
"name"
]
},
"something_else": {
"$id": "#something_else",
"properties": {
"foo": {
"type": "string"
}
},
"required": [
"foo"
]
},
"uuid": {
"$id": "#uuid",
"type": "string",
"pattern": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
},
"type": "object",
"$ref": "#something"
}
Attempting to resolve the second
schema and validate against it fails with:
System.ArgumentOutOfRangeException
HResult=0x80131502
Message=Specified argument was out of the range of valid values.
Source=System.Private.Uri
StackTrace:
at System.Uri..ctor(Uri baseUri, Uri relativeUri)
at Manatee.Json.Schema.JsonSchema.ResolveSubschema(JsonPointer pointer, Uri baseUri) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\JsonSchema.cs:line 262
at Manatee.Json.Schema.RefKeyword._ResolveLocalReference(Uri baseUri) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\Keywords\RefKeyword.cs:line 225
at Manatee.Json.Schema.RefKeyword._ResolveReference(SchemaValidationContext context) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\Keywords\RefKeyword.cs:line 214
at Manatee.Json.Schema.RefKeyword.Validate(SchemaValidationContext context) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\Keywords\RefKeyword.cs:line 72
at Manatee.Json.Schema.JsonSchema.Validate(SchemaValidationContext context) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\JsonSchema.cs:line 328
at Manatee.Json.Schema.PropertiesKeyword.Validate(SchemaValidationContext context) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\Keywords\PropertiesKeyword.cs:line 78
at Manatee.Json.Schema.JsonSchema.Validate(SchemaValidationContext context) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\JsonSchema.cs:line 328
at Manatee.Json.Schema.JsonSchema.Validate(JsonValue json) in C:\Users\Kent\Repository\Manatee.Json\Manatee.Json\Schema\JsonSchema.cs:line 192
at Harness.Program.Main(String[] args) in C:\Users\Kent\Repository\Manatee.Json\Harness\Program.cs:line 25
That's because the definitions
(and all other keywords) are ignored when they are sibling to a $ref
in draft 7 and below. You'll want to wrap the $ref
in an allOf
. (I didn't see that before.)
@kentcb did I answer your question?
@gregsdennis I never did get it to work, even when trying to wrap in allOf
. I gave up due to time pressure and did a hacky solution instead. Happy to close this anyway for now since I don't intend coming back to it just yet. Thanks Greg.
This is a question rather than a bug or feature request, but it may evolve into either.
I wrote the following code to illustrate my problem:
As you can see, I'm trying to resolve a schema within a schema so I can then go on to validate using it. My initial attempts at this revolved around using
schema.ResolveSubschema(JsonPointer.Parse("#/definitions/second"), new Uri("", UriKind.Relative))
basically because that felt like the right path to be going down. However, I simply could not get it to work.So I'm wondering whether there's a nicer/cleaner way of achieving this?