jsonschema: resolve remote references

Support remote references.
Most of the machinery was in place; we just had to define the
right loader, copy files from the test repo, and download
the meta-schema files from json-schema.org.

Change-Id: Ib588200ef0fa483641b9b53f9904f53b39dc4b82
Reviewed-on: https://go-review.googlesource.com/c/tools/+/670795
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Jonathan Amsterdam 2025-04-26 18:42:33 -04:00
commit 895b927ee8
24 changed files with 913 additions and 4 deletions

View file

@ -0,0 +1,342 @@
[
{
"description": "remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/integer.json"
},
"tests": [
{
"description": "remote ref valid",
"data": 1,
"valid": true
},
{
"description": "remote ref invalid",
"data": "a",
"valid": false
}
]
},
{
"description": "fragment within remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/subSchemas.json#/$defs/integer"
},
"tests": [
{
"description": "remote fragment valid",
"data": 1,
"valid": true
},
{
"description": "remote fragment invalid",
"data": "a",
"valid": false
}
]
},
{
"description": "anchor within remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/locationIndependentIdentifier.json#foo"
},
"tests": [
{
"description": "remote anchor valid",
"data": 1,
"valid": true
},
{
"description": "remote anchor invalid",
"data": "a",
"valid": false
}
]
},
{
"description": "ref within remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/subSchemas.json#/$defs/refToInteger"
},
"tests": [
{
"description": "ref within ref valid",
"data": 1,
"valid": true
},
{
"description": "ref within ref invalid",
"data": "a",
"valid": false
}
]
},
{
"description": "base URI change",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/",
"items": {
"$id": "baseUriChange/",
"items": {"$ref": "folderInteger.json"}
}
},
"tests": [
{
"description": "base URI change ref valid",
"data": [[1]],
"valid": true
},
{
"description": "base URI change ref invalid",
"data": [["a"]],
"valid": false
}
]
},
{
"description": "base URI change - change folder",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/scope_change_defs1.json",
"type" : "object",
"properties": {"list": {"$ref": "baseUriChangeFolder/"}},
"$defs": {
"baz": {
"$id": "baseUriChangeFolder/",
"type": "array",
"items": {"$ref": "folderInteger.json"}
}
}
},
"tests": [
{
"description": "number is valid",
"data": {"list": [1]},
"valid": true
},
{
"description": "string is invalid",
"data": {"list": ["a"]},
"valid": false
}
]
},
{
"description": "base URI change - change folder in subschema",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/scope_change_defs2.json",
"type" : "object",
"properties": {"list": {"$ref": "baseUriChangeFolderInSubschema/#/$defs/bar"}},
"$defs": {
"baz": {
"$id": "baseUriChangeFolderInSubschema/",
"$defs": {
"bar": {
"type": "array",
"items": {"$ref": "folderInteger.json"}
}
}
}
}
},
"tests": [
{
"description": "number is valid",
"data": {"list": [1]},
"valid": true
},
{
"description": "string is invalid",
"data": {"list": ["a"]},
"valid": false
}
]
},
{
"description": "root ref in remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/object",
"type": "object",
"properties": {
"name": {"$ref": "name-defs.json#/$defs/orNull"}
}
},
"tests": [
{
"description": "string is valid",
"data": {
"name": "foo"
},
"valid": true
},
{
"description": "null is valid",
"data": {
"name": null
},
"valid": true
},
{
"description": "object is invalid",
"data": {
"name": {
"name": null
}
},
"valid": false
}
]
},
{
"description": "remote ref with ref to defs",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/schema-remote-ref-ref-defs1.json",
"$ref": "ref-and-defs.json"
},
"tests": [
{
"description": "invalid",
"data": {
"bar": 1
},
"valid": false
},
{
"description": "valid",
"data": {
"bar": "a"
},
"valid": true
}
]
},
{
"description": "Location-independent identifier in remote ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/locationIndependentIdentifier.json#/$defs/refToInteger"
},
"tests": [
{
"description": "integer is valid",
"data": 1,
"valid": true
},
{
"description": "string is invalid",
"data": "foo",
"valid": false
}
]
},
{
"description": "retrieved nested refs resolve relative to their URI not $id",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/some-id",
"properties": {
"name": {"$ref": "nested/foo-ref-string.json"}
}
},
"tests": [
{
"description": "number is invalid",
"data": {
"name": {"foo": 1}
},
"valid": false
},
{
"description": "string is valid",
"data": {
"name": {"foo": "a"}
},
"valid": true
}
]
},
{
"description": "remote HTTP ref with different $id",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/different-id-ref-string.json"
},
"tests": [
{
"description": "number is invalid",
"data": 1,
"valid": false
},
{
"description": "string is valid",
"data": "foo",
"valid": true
}
]
},
{
"description": "remote HTTP ref with different URN $id",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/urn-ref-string.json"
},
"tests": [
{
"description": "number is invalid",
"data": 1,
"valid": false
},
{
"description": "string is valid",
"data": "foo",
"valid": true
}
]
},
{
"description": "remote HTTP ref with nested absolute ref",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/nested-absolute-ref-to-string.json"
},
"tests": [
{
"description": "number is invalid",
"data": 1,
"valid": false
},
{
"description": "string is valid",
"data": "foo",
"valid": true
}
]
},
{
"description": "$ref to $ref finds detached $anchor",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "http://localhost:1234/draft2020-12/detached-ref.json#/$defs/foo"
},
"tests": [
{
"description": "number is valid",
"data": 1,
"valid": true
},
{
"description": "non-number is invalid",
"data": "a",
"valid": false
}
]
}
]

4
jsonschema/testdata/remotes/README.md vendored Normal file
View file

@ -0,0 +1,4 @@
# JSON Schema test suite: remote references
These files were copied from
https://github.com/json-schema-org/JSON-Schema-Test-Suite/tree/83e866b46c9f9e7082fd51e83a61c5f2145a1ab7/remotes.

View file

@ -0,0 +1,5 @@
{
"$id": "http://localhost:1234/real-id-ref-string.json",
"$defs": {"bar": {"type": "string"}},
"$ref": "#/$defs/bar"
}

View file

@ -0,0 +1,4 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer"
}

View file

@ -0,0 +1,4 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer"
}

View file

@ -0,0 +1,4 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer"
}

View file

@ -0,0 +1,13 @@
{
"$id": "http://localhost:1234/draft2020-12/detached-dynamicref.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"foo": {
"$dynamicRef": "#detached"
},
"detached": {
"$dynamicAnchor": "detached",
"type": "integer"
}
}
}

View file

@ -0,0 +1,13 @@
{
"$id": "http://localhost:1234/draft2020-12/detached-ref.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"foo": {
"$ref": "#detached"
},
"detached": {
"$anchor": "detached",
"type": "integer"
}
}
}

View file

@ -0,0 +1,21 @@
{
"description": "extendible array",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/extendible-dynamic-ref.json",
"type": "object",
"properties": {
"elements": {
"type": "array",
"items": {
"$dynamicRef": "#elements"
}
}
},
"required": ["elements"],
"additionalProperties": false,
"$defs": {
"elements": {
"$dynamicAnchor": "elements"
}
}
}

View file

@ -0,0 +1,13 @@
{
"$id": "http://localhost:1234/draft2020-12/format-assertion-false.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/format-assertion": false
},
"$dynamicAnchor": "meta",
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/meta/core" },
{ "$ref": "https://json-schema.org/draft/2020-12/meta/format-assertion" }
]
}

View file

@ -0,0 +1,13 @@
{
"$id": "http://localhost:1234/draft2020-12/format-assertion-true.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/format-assertion": true
},
"$dynamicAnchor": "meta",
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/meta/core" },
{ "$ref": "https://json-schema.org/draft/2020-12/meta/format-assertion" }
]
}

View file

@ -0,0 +1,4 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer"
}

View file

@ -0,0 +1,12 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"refToInteger": {
"$ref": "#foo"
},
"A": {
"$anchor": "foo",
"type": "integer"
}
}
}

View file

@ -0,0 +1,13 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/metaschema-no-validation.json",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/core": true
},
"$dynamicAnchor": "meta",
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/meta/applicator" },
{ "$ref": "https://json-schema.org/draft/2020-12/meta/core" }
]
}

View file

@ -0,0 +1,14 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/metaschema-optional-vocabulary.json",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://json-schema.org/draft/2020-12/vocab/core": true,
"http://localhost:1234/draft/2020-12/vocab/custom": false
},
"$dynamicAnchor": "meta",
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/meta/validation" },
{ "$ref": "https://json-schema.org/draft/2020-12/meta/core" }
]
}

View file

@ -0,0 +1,16 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"orNull": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#"
}
]
}
},
"type": "string"
}

View file

@ -0,0 +1,7 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"foo": {"$ref": "string.json"}
}
}

View file

@ -0,0 +1,4 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "string"
}

View file

@ -0,0 +1,7 @@
{
"$id": "http://localhost:1234/draft2020-12/prefixItems.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"prefixItems": [
{"type": "string"}
]
}

View file

@ -0,0 +1,12 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://localhost:1234/draft2020-12/ref-and-defs.json",
"$defs": {
"inner": {
"properties": {
"bar": { "type": "string" }
}
}
},
"$ref": "#/$defs/inner"
}

Some files were not shown because too many files have changed in this diff Show more