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-07/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": "$id must be resolved against nearest parent, not just immediate parent", 641 "schema": { 642 "$id": "http://example.com/a.json", 643 "definitions": { 644 "x": { 645 "$id": "http://example.com/b/c.json", 646 "not": { 647 "definitions": { 648 "y": { 649 "$id": "d.json", 650 "type": "number" 651 } 652 } 653 } 654 } 655 }, 656 "allOf": [ 657 { 658 "$ref": "http://example.com/b/d.json" 659 } 660 ] 661 }, 662 "tests": [ 663 { 664 "description": "number is valid", 665 "data": 1, 666 "valid": true 667 }, 668 { 669 "description": "non-number is invalid", 670 "data": "a", 671 "valid": false 672 } 673 ] 674 }, 675 { 676 "description": "simple URN base URI with $ref via the URN", 677 "schema": { 678 "$comment": "URIs do not have to have HTTP(s) schemes", 679 "$id": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed", 680 "minimum": 30, 681 "properties": { 682 "foo": {"$ref": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed"} 683 } 684 }, 685 "tests": [ 686 { 687 "description": "valid under the URN IDed schema", 688 "data": {"foo": 37}, 689 "valid": true 690 }, 691 { 692 "description": "invalid under the URN IDed schema", 693 "data": {"foo": 12}, 694 "valid": false 695 } 696 ] 697 }, 698 { 699 "description": "simple URN base URI with JSON pointer", 700 "schema": { 701 "$comment": "URIs do not have to have HTTP(s) schemes", 702 "$id": "urn:uuid:deadbeef-1234-00ff-ff00-4321feebdaed", 703 "properties": { 704 "foo": {"$ref": "#/definitions/bar"} 705 }, 706 "definitions": { 707 "bar": {"type": "string"} 708 } 709 }, 710 "tests": [ 711 { 712 "description": "a string is valid", 713 "data": {"foo": "bar"}, 714 "valid": true 715 }, 716 { 717 "description": "a non-string is invalid", 718 "data": {"foo": 12}, 719 "valid": false 720 } 721 ] 722 }, 723 { 724 "description": "URN base URI with NSS", 725 "schema": { 726 "$comment": "RFC 8141 §2.2", 727 "$id": "urn:example:1/406/47452/2", 728 "properties": { 729 "foo": {"$ref": "#/definitions/bar"} 730 }, 731 "definitions": { 732 "bar": {"type": "string"} 733 } 734 }, 735 "tests": [ 736 { 737 "description": "a string is valid", 738 "data": {"foo": "bar"}, 739 "valid": true 740 }, 741 { 742 "description": "a non-string is invalid", 743 "data": {"foo": 12}, 744 "valid": false 745 } 746 ] 747 }, 748 { 749 "description": "URN base URI with r-component", 750 "schema": { 751 "$comment": "RFC 8141 §2.3.1", 752 "$id": "urn:example:foo-bar-baz-qux?+CCResolve:cc=uk", 753 "properties": { 754 "foo": {"$ref": "#/definitions/bar"} 755 }, 756 "definitions": { 757 "bar": {"type": "string"} 758 } 759 }, 760 "tests": [ 761 { 762 "description": "a string is valid", 763 "data": {"foo": "bar"}, 764 "valid": true 765 }, 766 { 767 "description": "a non-string is invalid", 768 "data": {"foo": 12}, 769 "valid": false 770 } 771 ] 772 }, 773 { 774 "description": "URN base URI with q-component", 775 "schema": { 776 "$comment": "RFC 8141 §2.3.2", 777 "$id": "urn:example:weather?=op=map&lat=39.56&lon=-104.85&datetime=1969-07-21T02:56:15Z", 778 "properties": { 779 "foo": {"$ref": "#/definitions/bar"} 780 }, 781 "definitions": { 782 "bar": {"type": "string"} 783 } 784 }, 785 "tests": [ 786 { 787 "description": "a string is valid", 788 "data": {"foo": "bar"}, 789 "valid": true 790 }, 791 { 792 "description": "a non-string is invalid", 793 "data": {"foo": 12}, 794 "valid": false 795 } 796 ] 797 }, 798 { 799 "description": "URN base URI with URN and JSON pointer ref", 800 "schema": { 801 "$id": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed", 802 "properties": { 803 "foo": {"$ref": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed#/definitions/bar"} 804 }, 805 "definitions": { 806 "bar": {"type": "string"} 807 } 808 }, 809 "tests": [ 810 { 811 "description": "a string is valid", 812 "data": {"foo": "bar"}, 813 "valid": true 814 }, 815 { 816 "description": "a non-string is invalid", 817 "data": {"foo": 12}, 818 "valid": false 819 } 820 ] 821 }, 822 { 823 "description": "URN base URI with URN and anchor ref", 824 "schema": { 825 "$id": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed", 826 "properties": { 827 "foo": {"$ref": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed#something"} 828 }, 829 "definitions": { 830 "bar": { 831 "$id": "#something", 832 "type": "string" 833 } 834 } 835 }, 836 "tests": [ 837 { 838 "description": "a string is valid", 839 "data": {"foo": "bar"}, 840 "valid": true 841 }, 842 { 843 "description": "a non-string is invalid", 844 "data": {"foo": 12}, 845 "valid": false 846 } 847 ] 848 }, 849 { 850 "description": "ref to if", 851 "schema": { 852 "allOf": [ 853 {"$ref": "http://example.com/ref/if"}, 854 { 855 "if": { 856 "$id": "http://example.com/ref/if", 857 "type": "integer" 858 } 859 } 860 ] 861 }, 862 "tests": [ 863 { 864 "description": "a non-integer is invalid due to the $ref", 865 "data": "foo", 866 "valid": false 867 }, 868 { 869 "description": "an integer is valid", 870 "data": 12, 871 "valid": true 872 } 873 ] 874 }, 875 { 876 "description": "ref to then", 877 "schema": { 878 "allOf": [ 879 {"$ref": "http://example.com/ref/then"}, 880 { 881 "then": { 882 "$id": "http://example.com/ref/then", 883 "type": "integer" 884 } 885 } 886 ] 887 }, 888 "tests": [ 889 { 890 "description": "a non-integer is invalid due to the $ref", 891 "data": "foo", 892 "valid": false 893 }, 894 { 895 "description": "an integer is valid", 896 "data": 12, 897 "valid": true 898 } 899 ] 900 }, 901 { 902 "description": "ref to else", 903 "schema": { 904 "allOf": [ 905 {"$ref": "http://example.com/ref/else"}, 906 { 907 "else": { 908 "$id": "http://example.com/ref/else", 909 "type": "integer" 910 } 911 } 912 ] 913 }, 914 "tests": [ 915 { 916 "description": "a non-integer is invalid due to the $ref", 917 "data": "foo", 918 "valid": false 919 }, 920 { 921 "description": "an integer is valid", 922 "data": 12, 923 "valid": true 924 } 925 ] 926 }, 927 { 928 "description": "ref with absolute-path-reference", 929 "schema": { 930 "$id": "http://example.com/ref/absref.json", 931 "definitions": { 932 "a": { 933 "$id": "http://example.com/ref/absref/foobar.json", 934 "type": "number" 935 }, 936 "b": { 937 "$id": "http://example.com/absref/foobar.json", 938 "type": "string" 939 } 940 }, 941 "allOf": [ 942 { "$ref": "/absref/foobar.json" } 943 ] 944 }, 945 "tests": [ 946 { 947 "description": "a string is valid", 948 "data": "foo", 949 "valid": true 950 }, 951 { 952 "description": "an integer is invalid", 953 "data": 12, 954 "valid": false 955 } 956 ] 957 }, 958 { 959 "description": "$id with file URI still resolves pointers - *nix", 960 "schema": { 961 "$id": "file:///folder/file.json", 962 "definitions": { 963 "foo": { 964 "type": "number" 965 } 966 }, 967 "allOf": [ 968 { 969 "$ref": "#/definitions/foo" 970 } 971 ] 972 }, 973 "tests": [ 974 { 975 "description": "number is valid", 976 "data": 1, 977 "valid": true 978 }, 979 { 980 "description": "non-number is invalid", 981 "data": "a", 982 "valid": false 983 } 984 ] 985 }, 986 { 987 "description": "$id with file URI still resolves pointers - windows", 988 "schema": { 989 "$id": "file:///c:/folder/file.json", 990 "definitions": { 991 "foo": { 992 "type": "number" 993 } 994 }, 995 "allOf": [ 996 { 997 "$ref": "#/definitions/foo" 998 } 999 ] 1000 }, 1001 "tests": [ 1002 { 1003 "description": "number is valid", 1004 "data": 1, 1005 "valid": true 1006 }, 1007 { 1008 "description": "non-number is invalid", 1009 "data": "a", 1010 "valid": false 1011 } 1012 ] 1013 }, 1014 { 1015 "description": "empty tokens in $ref json-pointer", 1016 "schema": { 1017 "definitions": { 1018 "": { 1019 "definitions": { 1020 "": { "type": "number" } 1021 } 1022 } 1023 }, 1024 "allOf": [ 1025 { 1026 "$ref": "#/definitions//definitions/" 1027 } 1028 ] 1029 }, 1030 "tests": [ 1031 { 1032 "description": "number is valid", 1033 "data": 1, 1034 "valid": true 1035 }, 1036 { 1037 "description": "non-number is invalid", 1038 "data": "a", 1039 "valid": false 1040 } 1041 ] 1042 } 1043] 1044