bougie-php-json 0.23.1

Byte-exact PHP json_encode output for two flag combinations Composer relies on (content-hash + JsonFile::encode).
Documentation

PHP-compatible JSON encoder. Byte-exact output for two PHP json_encode flag combinations Composer relies on:

  • [Mode::Hash] — json_encode($d, 0). The byte stream MD5'd into composer.lock's content-hash (see [super::lockfile::content_hash]). Compact, forward slashes escaped to \/, every code point ≥ 0x80 escaped to \uXXXX lowercase, surrogate pairs for code points

    0xFFFF. U+2028 / U+2029 fall under the same rule.

  • [Mode::Pretty] — json_encode($d, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE). The flag set Composer\Json\JsonFile::encode defaults to when writing composer.json / composer.lock. 4-space indent, raw /, raw UTF-8 for non-ASCII — except U+2028 / U+2029, which Composer keeps escaped (it doesn't pass JSON_UNESCAPED_LINE_TERMINATORS).

Shared rules (both modes):

  • "\", \\\.
  • Named escapes for 0x08 → \b, 0x09 → \t, 0x0A → \n, 0x0C → \f, 0x0D → \r.
  • Other C0 control bytes (0x00..0x07, 0x0B, 0x0E..0x1F) → \u00XX lowercase.
  • 0x7F (DEL) emitted raw — PHP's escape bitmap doesn't flag it.
  • Object keys take the same string-escape rules as string values.
  • Numbers: integers via plain decimal; floats via Rust's shortest- roundtrip f64::to_string, which matches PHP's zend_gcvt at serialize_precision = -1 (the post-7.1 default). Both PHP and Rust render integer-valued floats without a fractional part (1.0"1").