1[ 2 { 3 "description": "root pointer ref", 4 "schema": { 5 "properties": { 6 "foo": {"$ref": "#"} 7 }, 8 "additionalProperties": false 9 }, 10 "tests": [ 11 { 12 "description": "match", 13 "data": {"foo": false}, 14 "valid": true 15 }, 16 { 17 "description": "recursive match", 18 "data": {"foo": {"foo": false}}, 19 "valid": true 20 }, 21 { 22 "description": "mismatch", 23 "data": {"bar": false}, 24 "valid": false 25 }, 26 { 27 "description": "recursive mismatch", 28 "data": {"foo": {"bar": false}}, 29 "valid": false 30 } 31 ] 32 }, 33 { 34 "description": "relative pointer ref to object", 35 "schema": { 36 "properties": { 37 "foo": {"type": "integer"}, 38 "bar": {"$ref": "#/properties/foo"} 39 } 40 }, 41 "tests": [ 42 { 43 "description": "match", 44 "data": {"bar": 3}, 45 "valid": true 46 }, 47 { 48 "description": "mismatch", 49 "data": {"bar": true}, 50 "valid": false 51 } 52 ] 53 }, 54 { 55 "description": "relative pointer ref to array", 56 "schema": { 57 "items": [ 58 {"type": "integer"}, 59 {"$ref": "#/items/0"} 60 ] 61 }, 62 "tests": [ 63 { 64 "description": "match array", 65 "data": [1, 2], 66 "valid": true 67 }, 68 { 69 "description": "mismatch array", 70 "data": [1, "foo"], 71 "valid": false 72 } 73 ] 74 }, 75 { 76 "description": "escaped pointer ref", 77 "schema": { 78 "definitions": { 79 "tilde~field": {"type": "integer"}, 80 "slash/field": {"type": "integer"}, 81 "percent%field": {"type": "integer"} 82 }, 83 "properties": { 84 "tilde": {"$ref": "#/definitions/tilde~0field"}, 85 "slash": {"$ref": "#/definitions/slash~1field"}, 86 "percent": {"$ref": "#/definitions/percent%25field"} 87 } 88 }, 89 "tests": [ 90 { 91 "description": "slash invalid", 92 "data": {"slash": "aoeu"}, 93 "valid": false 94 }, 95 { 96 "description": "tilde invalid", 97 "data": {"tilde": "aoeu"}, 98 "valid": false 99 }, 100 { 101 "description": "percent invalid", 102 "data": {"percent": "aoeu"}, 103 "valid": false 104 }, 105 { 106 "description": "slash valid", 107 "data": {"slash": 123}, 108 "valid": true 109 }, 110 { 111 "description": "tilde valid", 112 "data": {"tilde": 123}, 113 "valid": true 114 }, 115 { 116 "description": "percent valid", 117 "data": {"percent": 123}, 118 "valid": true 119 } 120 ] 121 }, 122 { 123 "description": "nested refs", 124 "schema": { 125 "definitions": { 126 "a": {"type": "integer"}, 127 "b": {"$ref": "#/definitions/a"}, 128 "c": {"$ref": "#/definitions/b"} 129 }, 130 "allOf": [{ "$ref": "#/definitions/c" }] 131 }, 132 "tests": [ 133 { 134 "description": "nested ref valid", 135 "data": 5, 136 "valid": true 137 }, 138 { 139 "description": "nested ref invalid", 140 "data": "a", 141 "valid": false 142 } 143 ] 144 }, 145 { 146 "description": "ref overrides any sibling keywords", 147 "schema": { 148 "definitions": { 149 "reffed": { 150 "type": "array" 151 } 152 }, 153 "properties": { 154 "foo": { 155 "$ref": "#/definitions/reffed", 156 "maxItems": 2 157 } 158 } 159 }, 160 "tests": [ 161 { 162 "description": "ref valid", 163 "data": { "foo": [] }, 164 "valid": true 165 }, 166 { 167 "description": "ref valid, maxItems ignored", 168 "data": { "foo": [ 1, 2, 3] }, 169 "valid": true 170 }, 171 { 172 "description": "ref invalid", 173 "data": { "foo": "string" }, 174 "valid": false 175 } 176 ] 177 }, 178 { 179 "description": "$ref prevents a sibling id from changing the base uri", 180 "schema": { 181 "id": "http://localhost:1234/sibling_id/base/", 182 "definitions": { 183 "foo": { 184 "id": "http://localhost:1234/sibling_id/foo.json", 185 "type": "string" 186 }, 187 "base_foo": { 188 "$comment": "this canonical uri is http://localhost:1234/sibling_id/base/foo.json", 189 "id": "foo.json", 190 "type": "number" 191 } 192 }, 193 "allOf": [ 194 { 195 "$comment": "$ref resolves to http://localhost:1234/sibling_id/base/foo.json, not http://localhost:1234/sibling_id/foo.json", 196 "id": "http://localhost:1234/sibling_id/", 197 "$ref": "foo.json" 198 } 199 ] 200 }, 201 "tests": [ 202 { 203 "description": "$ref resolves to /definitions/base_foo, data does not validate", 204 "data": "a", 205 "valid": false 206 }, 207 { 208 "description": "$ref resolves to /definitions/base_foo, data validates", 209 "data": 1, 210 "valid": true 211 } 212 ] 213 }, 214 { 215 "description": "remote ref, containing refs itself", 216 "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 217 "tests": [ 218 { 219 "description": "remote ref valid", 220 "data": {"minLength": 1}, 221 "valid": true 222 }, 223 { 224 "description": "remote ref invalid", 225 "data": {"minLength": -1}, 226 "valid": false 227 } 228 ] 229 }, 230 { 231 "description": "property named $ref that is not a reference", 232 "schema": { 233 "properties": { 234 "$ref": {"type": "string"} 235 } 236 }, 237 "tests": [ 238 { 239 "description": "property named $ref valid", 240 "data": {"$ref": "a"}, 241 "valid": true 242 }, 243 { 244 "description": "property named $ref invalid", 245 "data": {"$ref": 2}, 246 "valid": false 247 } 248 ] 249 }, 250 { 251 "description": "property named $ref, containing an actual $ref", 252 "schema": { 253 "properties": { 254 "$ref": {"$ref": "#/definitions/is-string"} 255 }, 256 "definitions": { 257 "is-string": { 258 "type": "string" 259 } 260 } 261 }, 262 "tests": [ 263 { 264 "description": "property named $ref valid", 265 "data": {"$ref": "a"}, 266 "valid": true 267 }, 268 { 269 "description": "property named $ref invalid", 270 "data": {"$ref": 2}, 271 "valid": false 272 } 273 ] 274 }, 275 { 276 "description": "Recursive references between schemas", 277 "schema": { 278 "id": "http://localhost:1234/tree", 279 "description": "tree of nodes", 280 "type": "object", 281 "properties": { 282 "meta": {"type": "string"}, 283 "nodes": { 284 "type": "array", 285 "items": {"$ref": "node"} 286 } 287 }, 288 "required": ["meta", "nodes"], 289 "definitions": { 290 "node": { 291 "id": "http://localhost:1234/node", 292 "description": "node", 293 "type": "object", 294 "properties": { 295 "value": {"type": "number"}, 296 "subtree": {"$ref": "tree"} 297 }, 298 "required": ["value"] 299 } 300 } 301 }, 302 "tests": [ 303 { 304 "description": "valid tree", 305 "data": { 306 "meta": "root", 307 "nodes": [ 308 { 309 "value": 1, 310 "subtree": { 311 "meta": "child", 312 "nodes": [ 313 {"value": 1.1}, 314 {"value": 1.2} 315 ] 316 } 317 }, 318 { 319 "value": 2, 320 "subtree": { 321 "meta": "child", 322 "nodes": [ 323 {"value": 2.1}, 324 {"value": 2.2} 325 ] 326 } 327 } 328 ] 329 }, 330 "valid": true 331 }, 332 { 333 "description": "invalid tree", 334 "data": { 335 "meta": "root", 336 "nodes": [ 337 { 338 "value": 1, 339 "subtree": { 340 "meta": "child", 341 "nodes": [ 342 {"value": "string is invalid"}, 343 {"value": 1.2} 344 ] 345 } 346 }, 347 { 348 "value": 2, 349 "subtree": { 350 "meta": "child", 351 "nodes": [ 352 {"value": 2.1}, 353 {"value": 2.2} 354 ] 355 } 356 } 357 ] 358 }, 359 "valid": false 360 } 361 ] 362 }, 363 { 364 "description": "refs with quote", 365 "schema": { 366 "properties": { 367 "foo\"bar": {"$ref": "#/definitions/foo%22bar"} 368 }, 369 "definitions": { 370 "foo\"bar": {"type": "number"} 371 } 372 }, 373 "tests": [ 374 { 375 "description": "object with numbers is valid", 376 "data": { 377 "foo\"bar": 1 378 }, 379 "valid": true 380 }, 381 { 382 "description": "object with strings is invalid", 383 "data": { 384 "foo\"bar": "1" 385 }, 386 "valid": false 387 } 388 ] 389 }, 390 { 391 "description": "Location-independent identifier", 392 "schema": { 393 "allOf": [{ 394 "$ref": "#foo" 395 }], 396 "definitions": { 397 "A": { 398 "id": "#foo", 399 "type": "integer" 400 } 401 } 402 }, 403 "tests": [ 404 { 405 "data": 1, 406 "description": "match", 407 "valid": true 408 }, 409 { 410 "data": "a", 411 "description": "mismatch", 412 "valid": false 413 } 414 ] 415 }, 416 { 417 "description": "Location-independent identifier with base URI change in subschema", 418 "schema": { 419 "id": "http://localhost:1234/root", 420 "allOf": [{ 421 "$ref": "http://localhost:1234/nested.json#foo" 422 }], 423 "definitions": { 424 "A": { 425 "id": "nested.json", 426 "definitions": { 427 "B": { 428 "id": "#foo", 429 "type": "integer" 430 } 431 } 432 } 433 } 434 }, 435 "tests": [ 436 { 437 "data": 1, 438 "description": "match", 439 "valid": true 440 }, 441 { 442 "data": "a", 443 "description": "mismatch", 444 "valid": false 445 } 446 ] 447 }, 448 { 449 "description": "naive replacement of $ref with its destination is not correct", 450 "schema": { 451 "definitions": { 452 "a_string": { "type": "string" } 453 }, 454 "enum": [ 455 { "$ref": "#/definitions/a_string" } 456 ] 457 }, 458 "tests": [ 459 { 460 "description": "do not evaluate the $ref inside the enum, matching any string", 461 "data": "this is a string", 462 "valid": false 463 }, 464 { 465 "description": "match the enum exactly", 466 "data": { "$ref": "#/definitions/a_string" }, 467 "valid": true 468 } 469 ] 470 }, 471 { 472 "description": "id must be resolved against nearest parent, not just immediate parent", 473 "schema": { 474 "id": "http://example.com/a.json", 475 "definitions": { 476 "x": { 477 "id": "http://example.com/b/c.json", 478 "not": { 479 "definitions": { 480 "y": { 481 "id": "d.json", 482 "type": "number" 483 } 484 } 485 } 486 } 487 }, 488 "allOf": [ 489 { 490 "$ref": "http://example.com/b/d.json" 491 } 492 ] 493 }, 494 "tests": [ 495 { 496 "description": "number is valid", 497 "data": 1, 498 "valid": true 499 }, 500 { 501 "description": "non-number is invalid", 502 "data": "a", 503 "valid": false 504 } 505 ] 506 }, 507 { 508 "description": "id with file URI still resolves pointers - *nix", 509 "schema": { 510 "id": "file:///folder/file.json", 511 "definitions": { 512 "foo": { 513 "type": "number" 514 } 515 }, 516 "allOf": [ 517 { 518 "$ref": "#/definitions/foo" 519 } 520 ] 521 }, 522 "tests": [ 523 { 524 "description": "number is valid", 525 "data": 1, 526 "valid": true 527 }, 528 { 529 "description": "non-number is invalid", 530 "data": "a", 531 "valid": false 532 } 533 ] 534 }, 535 { 536 "description": "id with file URI still resolves pointers - windows", 537 "schema": { 538 "id": "file:///c:/folder/file.json", 539 "definitions": { 540 "foo": { 541 "type": "number" 542 } 543 }, 544 "allOf": [ 545 { 546 "$ref": "#/definitions/foo" 547 } 548 ] 549 }, 550 "tests": [ 551 { 552 "description": "number is valid", 553 "data": 1, 554 "valid": true 555 }, 556 { 557 "description": "non-number is invalid", 558 "data": "a", 559 "valid": false 560 } 561 ] 562 }, 563 { 564 "description": "empty tokens in $ref json-pointer", 565 "schema": { 566 "definitions": { 567 "": { 568 "definitions": { 569 "": { "type": "number" } 570 } 571 } 572 }, 573 "allOf": [ 574 { 575 "$ref": "#/definitions//definitions/" 576 } 577 ] 578 }, 579 "tests": [ 580 { 581 "description": "number is valid", 582 "data": 1, 583 "valid": true 584 }, 585 { 586 "description": "non-number is invalid", 587 "data": "a", 588 "valid": false 589 } 590 ] 591 } 592] 593