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 intocomposer.lock'scontent-hash(see [super::lockfile::content_hash]). Compact, forward slashes escaped to\/, every code point ≥ 0x80 escaped to\uXXXXlowercase, surrogate pairs for code points0xFFFF. 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 setComposer\Json\JsonFile::encodedefaults 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 passJSON_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) →
\u00XXlowercase. - 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'szend_gcvtatserialize_precision = -1(the post-7.1 default). Both PHP and Rust render integer-valued floats without a fractional part (1.0→"1").