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-06/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": "$ref to boolean schema true", 277 "schema": { 278 "allOf": [{ "$ref": "#/definitions/bool" }], 279 "definitions": { 280 "bool": true 281 } 282 }, 283 "tests": [ 284 { 285 "description": "any value is valid", 286 "data": "foo", 287 "valid": true 288 } 289 ] 290 }, 291 { 292 "description": "$ref to boolean schema false", 293 "schema": { 294 "allOf": [{ "$ref": "#/definitions/bool" }], 295 "definitions": { 296 "bool": false 297 } 298 }, 299 "tests": [ 300 { 301 "description": "any value is invalid", 302 "data": "foo", 303 "valid": false 304 } 305 ] 306 }, 307 { 308 "description": "Recursive references between schemas", 309 "schema": { 310 "$id": "http://localhost:1234/tree", 311 "description": "tree of nodes", 312 "type": "object", 313 "properties": { 314 "meta": {"type": "string"}, 315 "nodes": { 316 "type": "array", 317 "items": {"$ref": "node"} 318 } 319 }, 320 "required": ["meta", "nodes"], 321 "definitions": { 322 "node": { 323 "$id": "http://localhost:1234/node", 324 "description": "node", 325 "type": "object", 326 "properties": { 327 "value": {"type": "number"}, 328 "subtree": {"$ref": "tree"} 329 }, 330 "required": ["value"] 331 } 332 } 333 }, 334 "tests": [ 335 { 336 "description": "valid tree", 337 "data": { 338 "meta": "root", 339 "nodes": [ 340 { 341 "value": 1, 342 "subtree": { 343 "meta": "child", 344 "nodes": [ 345 {"value": 1.1}, 346 {"value": 1.2} 347 ] 348 } 349 }, 350 { 351 "value": 2, 352 "subtree": { 353 "meta": "child", 354 "nodes": [ 355 {"value": 2.1}, 356 {"value": 2.2} 357 ] 358 } 359 } 360 ] 361 }, 362 "valid": true 363 }, 364 { 365 "description": "invalid tree", 366 "data": { 367 "meta": "root", 368 "nodes": [ 369 { 370 "value": 1, 371 "subtree": { 372 "meta": "child", 373 "nodes": [ 374 {"value": "string is invalid"}, 375 {"value": 1.2} 376 ] 377 } 378 }, 379 { 380 "value": 2, 381 "subtree": { 382 "meta": "child", 383 "nodes": [ 384 {"value": 2.1}, 385 {"value": 2.2} 386 ] 387 } 388 } 389 ] 390 }, 391 "valid": false 392 } 393 ] 394 }, 395 { 396 "description": "refs with quote", 397 "schema": { 398 "properties": { 399 "foo\"bar": {"$ref": "#/definitions/foo%22bar"} 400 }, 401 "definitions": { 402 "foo\"bar": {"type": "number"} 403 } 404 }, 405 "tests": [ 406 { 407 "description": "object with numbers is valid", 408 "data": { 409 "foo\"bar": 1 410 }, 411 "valid": true 412 }, 413 { 414 "description": "object with strings is invalid", 415 "data": { 416 "foo\"bar": "1" 417 }, 418 "valid": false 419 } 420 ] 421 }, 422 { 423 "description": "Location-independent identifier", 424 "schema": { 425 "allOf": [{ 426 "$ref": "#foo" 427 }], 428 "definitions": { 429 "A": { 430 "$id": "#foo", 431 "type": "integer" 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": "Reference an anchor with a non-relative URI", 450 "schema": { 451 "$id": "https://example.com/schema-with-anchor", 452 "allOf": [{ 453 "$ref": "https://example.com/schema-with-anchor#foo" 454 }], 455 "definitions": { 456 "A": { 457 "$id": "#foo", 458 "type": "integer" 459 } 460 } 461 }, 462 "tests": [ 463 { 464 "data": 1, 465 "description": "match", 466 "valid": true 467 }, 468 { 469 "data": "a", 470 "description": "mismatch", 471 "valid": false 472 } 473 ] 474 }, 475 { 476 "description": "Location-independent identifier with base URI change in subschema", 477 "schema": { 478 "$id": "http://localhost:1234/root", 479 "allOf": [{ 480 "$ref": "http://localhost:1234/nested.json#foo" 481 }], 482 "definitions": { 483 "A": { 484 "$id": "nested.json", 485 "definitions": { 486 "B": { 487 "$id": "#foo", 488 "type": "integer" 489 } 490 } 491 } 492 } 493 }, 494 "tests": [ 495 { 496 "data": 1, 497 "description": "match", 498 "valid": true 499 }, 500 { 501 "data": "a", 502 "description": "mismatch", 503 "valid": false 504 } 505 ] 506 }, 507 { 508 "description": "naive replacement of $ref with its destination is not correct", 509 "schema": { 510 "definitions": { 511 "a_string": { "type": "string" } 512 }, 513 "enum": [ 514 { "$ref": "#/definitions/a_string" } 515 ] 516 }, 517 "tests": [ 518 { 519 "description": "do not evaluate the $ref inside the enum, matching any string", 520 "data": "this is a string", 521 "valid": false 522 }, 523 { 524 "description": "do not evaluate the $ref inside the enum, definition exact match", 525 "data": { "type": "string" }, 526 "valid": false 527 }, 528 { 529 "description": "match the enum exactly", 530 "data": { "$ref": "#/definitions/a_string" }, 531 "valid": true 532 } 533 ] 534 }, 535 { 536 "description": "refs with relative uris and defs", 537 "schema": { 538 "$id": "http://example.com/schema-relative-uri-defs1.json", 539 "properties": { 540 "foo": { 541 "$id": "schema-relative-uri-defs2.json", 542 "definitions": { 543 "inner": { 544 "properties": { 545 "bar": { "type": "string" } 546 } 547 } 548 }, 549 "allOf": [ { "$ref": "#/definitions/inner" } ] 550 } 551 }, 552 "allOf": [ { "$ref": "schema-relative-uri-defs2.json" } ] 553 }, 554 "tests": [ 555 { 556 "description": "invalid on inner field", 557 "data": { 558 "foo": { 559 "bar": 1 560 }, 561 "bar": "a" 562 }, 563 "valid": false 564 }, 565 { 566 "description": "invalid on outer field", 567 "data": { 568 "foo": { 569 "bar": "a" 570 }, 571 "bar": 1 572 }, 573 "valid": false 574 }, 575 { 576 "description": "valid on both fields", 577 "data": { 578 "foo": { 579 "bar": "a" 580 }, 581 "bar": "a" 582 }, 583 "valid": true 584 } 585 ] 586 }, 587 { 588 "description": "relative refs with absolute uris and defs", 589 "schema": { 590 "$id": "http://example.com/schema-refs-absolute-uris-defs1.json", 591 "properties": { 592 "foo": { 593 "$id": "http://example.com/schema-refs-absolute-uris-defs2.json", 594 "definitions": { 595 "inner": { 596 "properties": { 597 "bar": { "type": "string" } 598 } 599 } 600 }, 601 "allOf": [ { "$ref": "#/definitions/inner" } ] 602 } 603 }, 604 "allOf": [ { "$ref": "schema-refs-absolute-uris-defs2.json" } ] 605 }, 606 "tests": [ 607 { 608 "description": "invalid on inner field", 609 "data": { 610 "foo": { 611 "bar": 1 612 }, 613 "bar": "a" 614 }, 615 "valid": false 616 }, 617 { 618 "description": "invalid on outer field", 619 "data": { 620 "foo": { 621 "bar": "a" 622 }, 623 "bar": 1 624 }, 625 "valid": false 626 }, 627 { 628 "description": "valid on both fields", 629 "data": { 630 "foo": { 631 "bar": "a" 632 }, 633 "bar": "a" 634 }, 635 "valid": true 636 } 637 ] 638 }, 639 { 640 "description": "simple URN base URI with $ref via the URN", 641 "schema": { 642 "$comment": "URIs do not have to have HTTP(s) schemes", 643 "$id": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed", 644 "minimum": 30, 645 "properties": { 646 "foo": {"$ref": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed"} 647 } 648 }, 649 "tests": [ 650 { 651 "description": "valid under the URN IDed schema", 652 "data": {"foo": 37}, 653 "valid": true 654 }, 655 { 656 "description": "invalid under the URN IDed schema", 657 "data": {"foo": 12}, 658 "valid": false 659 } 660 ] 661 }, 662 { 663 "description": "simple URN base URI with JSON pointer", 664 "schema": { 665 "$comment": "URIs do not have to have HTTP(s) schemes", 666 "$id": "urn:uuid:deadbeef-1234-00ff-ff00-4321feebdaed", 667 "properties": { 668 "foo": {"$ref": "#/definitions/bar"} 669 }, 670 "definitions": { 671 "bar": {"type": "string"} 672 } 673 }, 674 "tests": [ 675 { 676 "description": "a string is valid", 677 "data": {"foo": "bar"}, 678 "valid": true 679 }, 680 { 681 "description": "a non-string is invalid", 682 "data": {"foo": 12}, 683 "valid": false 684 } 685 ] 686 }, 687 { 688 "description": "URN base URI with NSS", 689 "schema": { 690 "$comment": "RFC 8141 §2.2", 691 "$id": "urn:example:1/406/47452/2", 692 "properties": { 693 "foo": {"$ref": "#/definitions/bar"} 694 }, 695 "definitions": { 696 "bar": {"type": "string"} 697 } 698 }, 699 "tests": [ 700 { 701 "description": "a string is valid", 702 "data": {"foo": "bar"}, 703 "valid": true 704 }, 705 { 706 "description": "a non-string is invalid", 707 "data": {"foo": 12}, 708 "valid": false 709 } 710 ] 711 }, 712 { 713 "description": "URN base URI with r-component", 714 "schema": { 715 "$comment": "RFC 8141 §2.3.1", 716 "$id": "urn:example:foo-bar-baz-qux?+CCResolve:cc=uk", 717 "properties": { 718 "foo": {"$ref": "#/definitions/bar"} 719 }, 720 "definitions": { 721 "bar": {"type": "string"} 722 } 723 }, 724 "tests": [ 725 { 726 "description": "a string is valid", 727 "data": {"foo": "bar"}, 728 "valid": true 729 }, 730 { 731 "description": "a non-string is invalid", 732 "data": {"foo": 12}, 733 "valid": false 734 } 735 ] 736 }, 737 { 738 "description": "URN base URI with q-component", 739 "schema": { 740 "$comment": "RFC 8141 §2.3.2", 741 "$id": "urn:example:weather?=op=map&lat=39.56&lon=-104.85&datetime=1969-07-21T02:56:15Z", 742 "properties": { 743 "foo": {"$ref": "#/definitions/bar"} 744 }, 745 "definitions": { 746 "bar": {"type": "string"} 747 } 748 }, 749 "tests": [ 750 { 751 "description": "a string is valid", 752 "data": {"foo": "bar"}, 753 "valid": true 754 }, 755 { 756 "description": "a non-string is invalid", 757 "data": {"foo": 12}, 758 "valid": false 759 } 760 ] 761 }, 762 { 763 "description": "URN base URI with URN and JSON pointer ref", 764 "schema": { 765 "$id": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed", 766 "properties": { 767 "foo": {"$ref": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed#/definitions/bar"} 768 }, 769 "definitions": { 770 "bar": {"type": "string"} 771 } 772 }, 773 "tests": [ 774 { 775 "description": "a string is valid", 776 "data": {"foo": "bar"}, 777 "valid": true 778 }, 779 { 780 "description": "a non-string is invalid", 781 "data": {"foo": 12}, 782 "valid": false 783 } 784 ] 785 }, 786 { 787 "description": "URN base URI with URN and anchor ref", 788 "schema": { 789 "$id": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed", 790 "properties": { 791 "foo": {"$ref": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed#something"} 792 }, 793 "definitions": { 794 "bar": { 795 "$id": "#something", 796 "type": "string" 797 } 798 } 799 }, 800 "tests": [ 801 { 802 "description": "a string is valid", 803 "data": {"foo": "bar"}, 804 "valid": true 805 }, 806 { 807 "description": "a non-string is invalid", 808 "data": {"foo": 12}, 809 "valid": false 810 } 811 ] 812 }, 813 { 814 "description": "ref with absolute-path-reference", 815 "schema": { 816 "$id": "http://example.com/ref/absref.json", 817 "definitions": { 818 "a": { 819 "$id": "http://example.com/ref/absref/foobar.json", 820 "type": "number" 821 }, 822 "b": { 823 "$id": "http://example.com/absref/foobar.json", 824 "type": "string" 825 } 826 }, 827 "allOf": [ 828 { "$ref": "/absref/foobar.json" } 829 ] 830 }, 831 "tests": [ 832 { 833 "description": "a string is valid", 834 "data": "foo", 835 "valid": true 836 }, 837 { 838 "description": "an integer is invalid", 839 "data": 12, 840 "valid": false 841 } 842 ] 843 }, 844 { 845 "description": "$id with file URI still resolves pointers - *nix", 846 "schema": { 847 "$id": "file:///folder/file.json", 848 "definitions": { 849 "foo": { 850 "type": "number" 851 } 852 }, 853 "allOf": [ 854 { 855 "$ref": "#/definitions/foo" 856 } 857 ] 858 }, 859 "tests": [ 860 { 861 "description": "number is valid", 862 "data": 1, 863 "valid": true 864 }, 865 { 866 "description": "non-number is invalid", 867 "data": "a", 868 "valid": false 869 } 870 ] 871 }, 872 { 873 "description": "$id with file URI still resolves pointers - windows", 874 "schema": { 875 "$id": "file:///c:/folder/file.json", 876 "definitions": { 877 "foo": { 878 "type": "number" 879 } 880 }, 881 "allOf": [ 882 { 883 "$ref": "#/definitions/foo" 884 } 885 ] 886 }, 887 "tests": [ 888 { 889 "description": "number is valid", 890 "data": 1, 891 "valid": true 892 }, 893 { 894 "description": "non-number is invalid", 895 "data": "a", 896 "valid": false 897 } 898 ] 899 }, 900 { 901 "description": "empty tokens in $ref json-pointer", 902 "schema": { 903 "definitions": { 904 "": { 905 "definitions": { 906 "": { "type": "number" } 907 } 908 } 909 }, 910 "allOf": [ 911 { 912 "$ref": "#/definitions//definitions/" 913 } 914 ] 915 }, 916 "tests": [ 917 { 918 "description": "number is valid", 919 "data": 1, 920 "valid": true 921 }, 922 { 923 "description": "non-number is invalid", 924 "data": "a", 925 "valid": false 926 } 927 ] 928 } 929] 930