{
  "description": "RFC 8785 canonical JSON as A5.4 uses it: each accepted input with its exact canonical text, that text as UTF-8 in hexadecimal and its SHA-256; each refused input with the strict-parsing rule it breaks.",
  "vectors": [
    {
      "id": "member-order",
      "description": "Members are sorted at every depth; array order is kept.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"b\":true,\"a\":[3,1,2],\"c\":{\"z\":null,\"y\":\"y\"}}",
      "expected": {
        "valid": true,
        "canonical": "{\"a\":[3,1,2],\"b\":true,\"c\":{\"y\":\"y\",\"z\":null}}",
        "canonical_utf8_hex": "7b2261223a5b332c312c325d2c2262223a747275652c2263223a7b2279223a2279222c227a223a6e756c6c7d7d",
        "sha256": "64e775f68caa6efb960ac2b0a24a3fb0b31496b60c8502242ddf54aa3e493780"
      }
    },
    {
      "id": "member-order-utf16",
      "description": "Member names sort by their UTF-16 code units, not by code points: U+1F600 (a surrogate pair starting D83D) sorts before U+FB33. The empty name sorts first. Characters outside ASCII are written as UTF-8, not escaped.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"\\u20ac\":1,\"\\ud83d\\ude00\":2,\"\\ufb33\":3,\"\\u0080\":4,\"a\":5,\"A\":6,\"1\":7,\"\":8}",
      "expected": {
        "valid": true,
        "canonical": "{\"\":8,\"1\":7,\"A\":6,\"a\":5,\"\":4,\"€\":1,\"😀\":2,\"דּ\":3}",
        "canonical_utf8_hex": "7b22223a382c2231223a372c2241223a362c2261223a352c22c280223a342c22e282ac223a312c22f09f9880223a322c22efacb3223a337d",
        "sha256": "8c6f18170a76d7a7c03e275b89ae8dba7f7b5d522c708a1191dfef50b70a9f74"
      }
    },
    {
      "id": "unicode-unescaped",
      "description": "Escaped characters outside ASCII are written as UTF-8 in the canonical form.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"text\":\"Zo\\u00eb \\u4e2d\\u6587 \\ud83d\\ude00\"}",
      "expected": {
        "valid": true,
        "canonical": "{\"text\":\"Zoë 中文 😀\"}",
        "canonical_utf8_hex": "7b2274657874223a225a6fc3ab20e4b8ade6968720f09f9880227d",
        "sha256": "f5179a395a1f560afd67f419c311618fd2c416ddcf8953ae718b03628fccfc20"
      }
    },
    {
      "id": "no-normalisation",
      "description": "Strings are not Unicode-normalised: a precomposed and a decomposed letter stay different.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"text\":\"\\u00e9\",\"decomposed\":\"e\\u0301\"}",
      "expected": {
        "valid": true,
        "canonical": "{\"decomposed\":\"é\",\"text\":\"é\"}",
        "canonical_utf8_hex": "7b226465636f6d706f736564223a2265cc81222c2274657874223a22c3a9227d",
        "sha256": "a88ffebf5ca0841eb1f4466f9be2fcb5293379cbd7b1b028527363384d20f77d"
      }
    },
    {
      "id": "escapes",
      "description": "Control characters are escaped, with the short forms for backspace, tab, line feed, form feed and carriage return and lower-case hexadecimal otherwise; quotation mark and reverse solidus are escaped; solidus, DEL, U+2028 and U+2029 are not.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"s\":\"\\u0000\\u0007\\b\\t\\n\\u000B\\f\\r\\u001F\\\"\\\\\\/\\u007f\\u2028\\u2029\"}",
      "expected": {
        "valid": true,
        "canonical": "{\"s\":\"\\u0000\\u0007\\b\\t\\n\\u000b\\f\\r\\u001f\\\"\\\\/  \"}",
        "canonical_utf8_hex": "7b2273223a225c75303030305c75303030375c625c745c6e5c75303030625c665c725c75303031665c225c5c2f7fe280a8e280a9227d",
        "sha256": "6a84b9249016110118198ef8437d853c4be9567f072aea3f2b52d2591d4f64ba"
      }
    },
    {
      "id": "whitespace",
      "description": "Insignificant whitespace is removed.",
      "checks": [
        "SIGN-01"
      ],
      "input": " {\n  \"a\" : [ 1 , 2 ] ,\t\"b\" : { }\r\n} ",
      "expected": {
        "valid": true,
        "canonical": "{\"a\":[1,2],\"b\":{}}",
        "canonical_utf8_hex": "7b2261223a5b312c325d2c2262223a7b7d7d",
        "sha256": "8c547cce7ccb1b89359479c0b71a0a4b62acfc54a2b2780fd34aaeb75f9e44b7"
      }
    },
    {
      "id": "literals-and-empty-values",
      "description": "Literals, empty strings, arrays and objects.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"t\":true,\"f\":false,\"n\":null,\"e\":\"\",\"a\":[],\"o\":{}}",
      "expected": {
        "valid": true,
        "canonical": "{\"a\":[],\"e\":\"\",\"f\":false,\"n\":null,\"o\":{},\"t\":true}",
        "canonical_utf8_hex": "7b2261223a5b5d2c2265223a22222c2266223a66616c73652c226e223a6e756c6c2c226f223a7b7d2c2274223a747275657d",
        "sha256": "09d0cf4652ab55492534f86f3cf0d353178b28aa1e0629d16fe83b3e647b98f8"
      }
    },
    {
      "id": "nested-order",
      "description": "Objects inside arrays are sorted too.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[{\"b\":{\"d\":1,\"c\":2},\"a\":[{\"f\":1,\"e\":2}]}]",
      "expected": {
        "valid": true,
        "canonical": "[{\"a\":[{\"e\":2,\"f\":1}],\"b\":{\"c\":2,\"d\":1}}]",
        "canonical_utf8_hex": "5b7b2261223a5b7b2265223a322c2266223a317d5d2c2262223a7b2263223a322c2264223a317d7d5d",
        "sha256": "03944f82dc3110b938774cc91cdbcb3ca030241d105fb528f0c83519b37ebd05"
      }
    },
    {
      "id": "integers",
      "description": "Integers, including negative zero and integers written with a fraction or an exponent, take their shortest form.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[0,-0,1,-1,42,9007199254740991,-9007199254740991,100.0,1e2,1E+2,1.0e2,-0.0]",
      "expected": {
        "valid": true,
        "canonical": "[0,0,1,-1,42,9007199254740991,-9007199254740991,100,100,100,100,0]",
        "canonical_utf8_hex": "5b302c302c312c2d312c34322c393030373139393235343734303939312c2d393030373139393235343734303939312c3130302c3130302c3130302c3130302c305d",
        "sha256": "7aca4296cac523b861e8459e2552f0190b0082e3d8c587dae36d28123f63937c"
      }
    },
    {
      "id": "integer-two-to-the-fifty-third",
      "description": "Binary64 holds 2^53 exactly, so the A5.4 number rule accepts it, although I-JSON advises against integers this large.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[9007199254740992]",
      "expected": {
        "valid": true,
        "canonical": "[9007199254740992]",
        "canonical_utf8_hex": "5b393030373139393235343734303939325d",
        "sha256": "5dc10964d69741c9924433db7b0e8fe5b0ac6fac6a5dd6d142b8c4e05e2162c3"
      }
    },
    {
      "id": "numbers",
      "description": "Numbers that are not integers take the ECMAScript shortest round-trip form RFC 8785 requires: exponents from 1e21 upwards and below 1e-6, plain decimals between.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[0.1,1e23,1.5e-7,0.000001,1e-7,1e21,1e20,123456789012345680000,2.5e-3,5e-324,1.7976931348623157e308,-1.5,333333333.3333333,0.30000000000000004]",
      "expected": {
        "valid": true,
        "canonical": "[0.1,1e+23,1.5e-7,0.000001,1e-7,1e+21,100000000000000000000,123456789012345680000,0.0025,5e-324,1.7976931348623157e+308,-1.5,333333333.3333333,0.30000000000000004]",
        "canonical_utf8_hex": "5b302e312c31652b32332c312e35652d372c302e3030303030312c31652d372c31652b32312c3130303030303030303030303030303030303030302c3132333435363738393031323334353638303030302c302e303032352c35652d3332342c312e37393736393331333438363233313537652b3330382c2d312e352c3333333333333333332e333333333333332c302e33303030303030303030303030303030345d",
        "sha256": "941ede9187fe511f2c5580dab9344191786214abb30572f4f0b83c72d5be5967"
      }
    },
    {
      "id": "duplicate-member-equal-values",
      "description": "A repeated member name is refused, even with equal values.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"a\":1,\"a\":1}",
      "expected": {
        "valid": false,
        "reason": "duplicate_member"
      }
    },
    {
      "id": "duplicate-member-after-escape",
      "description": "Member names are compared after escapes are decoded: \"\\u0061\" is \"a\".",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"a\":1,\"\\u0061\":2}",
      "expected": {
        "valid": false,
        "reason": "duplicate_member"
      }
    },
    {
      "id": "duplicate-member-nested",
      "description": "A repeated member is refused at any depth.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"x\":[{\"b\":1,\"b\":2}]}",
      "expected": {
        "valid": false,
        "reason": "duplicate_member"
      }
    },
    {
      "id": "lone-high-surrogate",
      "description": "A lone surrogate in a string is not I-JSON.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"s\":\"\\ud800\"}",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "lone-low-surrogate-in-name",
      "description": "A lone surrogate in a member name is not I-JSON.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"\\udc00\":1}",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "noncharacter-ffff",
      "description": "A noncharacter is not I-JSON.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"s\":\"\\uffff\"}",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "noncharacter-fdd0",
      "description": "U+FDD0 to U+FDEF are noncharacters too.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"s\":\"\\ufdd0\"}",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "number-magnitude",
      "description": "A number beyond the magnitude of binary64 is refused, not read as infinity.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[1E400]",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "number-underflow",
      "description": "A number too small for binary64 is refused, not read as zero.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[1e-400]",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "number-precision",
      "description": "A number with more precision than binary64 provides is refused (the RFC 7493 example).",
      "checks": [
        "SIGN-01"
      ],
      "input": "[3.141592653589793238462643383279]",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "number-excess-digits",
      "description": "The decimal written must equal the shortest decimal of the double it parses to: 0.10000000000000001 parses to the double 0.1, so it is refused while 0.1 is accepted.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[0.10000000000000001]",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "integer-beyond-two-to-the-fifty-third",
      "description": "2^53 + 1 parses to 2^53, so its written value is lost and it is refused.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[9007199254740993]",
      "expected": {
        "valid": false,
        "reason": "not_i_json"
      }
    },
    {
      "id": "unescaped-control-character",
      "description": "RFC 8259 requires control characters in strings to be escaped; a raw U+0001 is refused.",
      "checks": [
        "SIGN-01"
      ],
      "input": "{\"s\":\"a\u0001b\"}",
      "expected": {
        "valid": false,
        "reason": "malformed_json"
      }
    },
    {
      "id": "nan-literal",
      "description": "NaN and Infinity are not JSON.",
      "checks": [
        "SIGN-01"
      ],
      "input": "[NaN]",
      "expected": {
        "valid": false,
        "reason": "malformed_json"
      }
    }
  ]
}
