# Jcs
A pure Elixir implementation of
[RFC 8785: JSON Canonicalization Scheme (JCS)](https://www.rfc-editor.org/rfc/rfc8785).
JCS can be used to establish a canonical deterministic representation
of linked JSON data. These represenations can then be used in
establishing identity proofs.
For an example, see the [W3C Data Integrity 1.0 report](https://www.w3.org/community/reports/credentials/CG-FINAL-data-integrity-20220722/#proofs).
That report also gives as an example usage identity proofs, the ability to
authenticate as an entity identified by a [Decentralized Identifier (DID)](https://www.w3.org/TR/did-core/).
The JSON encoding here is probably orders of magnitude slower than the Jason
library. There is no attempt here to decent better memory management in
building the output, and sorting object properties based on their
UTF-16-encoded keys can probably be greatly improved also.
Pull requests are gratefully encouraged!
Code is based on the [Python 3 jcs package](https://github.com/titusz/jcs).
Test suites are from the [Java implementation by Samuel Erdtman](https://github.com/erdtman/java-json-canonicalization)
and from [Appendix B of RFC 8785](https://www.rfc-editor.org/rfc/rfc8785#section-appendix.b).
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `jcs` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:jcs, "~> 0.1.1"}
]
end
```
## Usage
```elixir
Jcs.encode(%{"aa" => 200, "b" => 100.0, "西葛西駅" => [200, "station"], "a" => "hello\tworld!"})
"{\"a\":\"hello\\tworld!\",\"aa\":200,\"b\":100,\"西葛西駅\":[200,\"station\"]}"
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/jcs>.
## Notes on encoding floating point values
This library depends on using the Ryu algorithm that was added to Erlang
in OTP 25, via the `:erlang.float_to_binary/2` function and the new `:short`
option. See https://www.erlang.org/blog/my-otp-25-highlights/#new-option-short-for-erlangfloat_to_list2-and-erlangfloat_to_binary2 for
more information.
Also note that while the RFC states that the Ryu algorithm is compliant for
encoding floats, the Erlang implementation encodes integral values like 1e+23
as "1.0e23", where as RFC 8785 would encode this as "1e+23".
When attempting to handle all the test cases in the RFC appendix, it appears
as though not all of the IEEE754 double value examples are able to be encoded
into Elixir floats. These are commented out as "Elixir can not set this value"
in the JcsNumbersTest test module.