Skip to content

v3.2.0

Choose a tag to compare

@HelgeSverre HelgeSverre released this 08 Jul 14:58
· 3 commits to main since this release

Changes in v3.2.0

This release brings the library into conformance with TOON Specification v3.3 (upstream advanced v3.0 → v3.3) and adds a validation API.

Added

  • TOON Specification v3.3 compliance. See docs/SPEC.md and docs/CHANGELOG.md.
  • Unicode escapes (§7.1): the encoder emits C0 control characters (U+0000–U+001F except \n, \r, \t) as \uXXXX; the decoder accepts \uXXXX (case-insensitive hex) and rejects lone surrogates and escapes with fewer than four hex digits.
  • Empty-array decoding (§9.1): the decoder now accepts the canonical [] and key: [] forms in addition to the legacy [0]: / key[0]: forms.
  • Validation API: Toon::validate(), toon_validate() and toon_validate_lenient() for checking TOON syntax without decoding.
  • Spec conformance tests in tests/Spec/Version31To33ComplianceTest.php.

Changed

  • Number formatting (§2): finite numbers use canonical decimal only for n = 0 or 1e-6 ≤ |n| < 1e21; values outside that range use exponent notation (lowercase e, explicit sign, e.g. 1e+21, 1e-7). Large in-domain floats are no longer quoted as strings, and very small numbers no longer underflow to 0.
  • Control characters are no longer rejected on encode — they are escaped and preserved as data (§15).
  • Strict decoding now rejects leading-zero / malformed bracket lengths such as [03] (§6, §14.2), header delimiter mismatches where the bracket delimiter differs from the field-list delimiter, e.g. rows[2|]{a,b}: (§6, §14.2), and duplicate sibling keys at the same depth (§8, §14.4). Non-strict mode treats malformed bracket tokens as literal keys and applies last-write-wins for duplicate keys.

Fixed

  • Decoder: quoted object keys containing colons (e.g. "App\Controller::method") now decode correctly (#4, #5).
  • Decoder: key: [] previously decoded to null and a bare [] crashed with an uninitialized-offset warning; both now decode to an empty array.
  • Decoder — single-line list items (§9.2/§9.4/§10): a list item whose entire content is on the hyphen line now decodes by shape instead of as a plain string — - [M]: … → inner array, - key: … → object, bare - → empty object. This fixes round-trips for arrays of arrays and lists of single-field objects.
  • Decoder — empty document (§5): an empty or whitespace-only document decodes to an empty object in both modes, instead of throwing (strict) or returning null (lenient).
  • Decoder — bare key: (§8): decodes to an empty object, not null.
  • Decoder — quoted header keys (§7.4): a quoted key prefix such as "my-key"[3]: is unescaped.
  • Decoder — empty inline/tabular tokens (§9.1/§11.2): decode to the empty string instead of throwing (e.g. [3]: a,,b['a','','b']).
  • Decoder — backslash handling (§7.1/§11.2): an unquoted backslash is a literal character (escapes apply only inside quoted strings), and colon detection tracks quote state so a key ending in an escaped backslash ("a\\": c) parses.
  • Options (§12): EncodeOptions/DecodeOptions reject indent < 1; EncodeOptions::compact() now uses indent: 1 so nested output round-trips.
  • Validation: Toon::validate() now runs the full decoder internally and returns false only when decode() throws, so validation and decoding can never disagree. The separate validator implementation was removed.

Full Changelog: v3.1.0...v3.2.0