| human-readable can actually be a drawback for formats specifically designed to be non-malleable, precisely because they invite opening in a text editor and appending some keys in whatever order.
fwiw, https://preserves.dev/ is well-designed, has a superset of JSON types, and has both a textual format and a binary format with a rigidly-defined canonical representation for the latter. however it's also a bit obscure and won't have as wide library support as alternatives so I can understand not going with it. the Spritely/Agoric/Cap'n Proto standardization effort OCapN uses it as Syrup, which is a separate canonical-but-made-up-of-printable-characters serialization of it https://github.com/ocapn/syrup#pseudo-specification.
more well-known alternatives:
- deterministic CBOR serialization, buuuut there are like three versions of it so caveat emptor https://www.imperialviolet.org/2022/04/17/canonsofcbor.html
- canonical s-expressions
- bencode
- …ASN.1 BER? 🙃
also, if you don't actually need a flexible/extensible format, defining your own very simple rigid serialization isn't a sin when you want cryptographic canonicity. (just make sure it's actually non-ambiguous and preferably can't be corrupted into another valid message by truncation, especially if you might be concatenating multiple messages.)
|