From 4c8e3cad8174591368f2bf411d5bb89e6f72427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muska=C5=82a?= Date: Tue, 20 Feb 2024 15:50:00 +0000 Subject: [PATCH] Formatting fixes --- eeps/eep-0068.md | 51 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/eeps/eep-0068.md b/eeps/eep-0068.md index ec1868e..94b8753 100644 --- a/eeps/eep-0068.md +++ b/eeps/eep-0068.md @@ -5,10 +5,11 @@ Erlang-Version: Post-History: **** -# EEP 68: JSON library +EEP 68: JSON library ---- -## Abstract +Abstract +======== This EEP proposes introducing a module `json` to the Erlang standard library with support for encoding and decoding [JSON][1] documents @@ -16,9 +17,11 @@ from and to Erlang data structures. The main reason is to cover a gap in the Erlang standard library with regards to such a vastly popular and widespread data format. -## Rationale +Rationale +========= JSON is commonly used in many different use-cases: + * by web services as a lightweight and human-readable data interchange format; * as a configuration language in static files; * as data interchange format by developer tooling; @@ -44,6 +47,7 @@ as an extensible and highly-customisable API with common underlying implementation. This EEP proposes a JSON library which: + * should be easy to adopt in large codebases using one of the popular, existing, open-source JSON libraries; * will allow the existing open-source libraries with custom features @@ -53,6 +57,7 @@ This EEP proposes a JSON library which: leading open-source JSON libraries. The proposed JSON library will provide: + * JSON encoding, allowing for single-pass encoding of custom data types –- in particular, for Elixir, integrating with a protocol through a thin layer (implemented outside of OTP); @@ -65,9 +70,11 @@ The proposed JSON library will provide: the decoder should pass the entire [JSONTestSuite][JSONTestSuite]; * simple API for common use-cases with canonical data type mapping. -## Design choices +Design choices +============== -### Data mapping +Data mapping +------------ We propose, in the "canonical" API to map JSON data structues to Erlang and back in the following way: @@ -97,7 +104,8 @@ even with custom decoders -- since JSON has such a limited data-type options, compared to Erlang, some information will be commonly be lost, for example, coercing all keys in maps to binaries. -### Streaming vs value-based parser +Streaming vs value-based parser +------------------------------- When it comes to data-structure parsers it's common to encounter two types: ones that given the data produce a complete parsed value, @@ -128,6 +136,7 @@ First, a simple, value-based API: Error handling is achieved through exceptions. The following errors are possible: + ```erlang -type error() :: unexpected_end | @@ -169,6 +178,7 @@ API that the decoder will use to produce values from the data it parses. This allows the user to fully customize the decoded format, including features seen in open-source JSON libraries: + * decoding string keys as atoms; * decoding objects as lists of pairs; * decoding floats as custom structures with decimal precision; @@ -201,7 +211,8 @@ All the callbacks are optional and have a default value corresponding to the * for `string`: `fun (Value) -> Value end` * for `null`: the atom `null` -### Incomplete data parsing +Incomplete data parsing +----------------------- We propose a future enhancement to the full `decode/3` API, where it can return an `{incomplete, continuation()}` value that can be used to @@ -214,7 +225,8 @@ from a TCP socket). {incomplete, continuation()}. ``` -### Encoding API +Encoding API +------------ For encoding this EEP again proposes two separate sets of APIs. A simple API using "canonical" data types: @@ -268,7 +280,8 @@ that will always produce purely ASCII messages encoding all higher unicode values with the `\u` escape sequences. -### Formatting and pretty-printing +Formatting and pretty-printing +------------------------------ This EEP further proposes an additional API for formatting (and pretty-printing) JSON messages. This API consists of transforming a textual JSON message into @@ -290,22 +303,28 @@ services, therefore the overhead of a two-pass formatting is deemed acceptable. -spec format(iodata(), format_option()) -> iodata(). ``` -## Reference Implementation +Reference Implementation +======================== [PR-8111][PR] Implements the `encode/1`, `encode/2`, `decode/1`, and `decode/3` functions as proposed in this EEP. The formatting API and the support for incomplete message decoding is left as a follow-up task. -## Appendix +Appendix +======== -### Example of a decoding trace +Example of a decoding trace +--------------------------- Given the following data: + ```json {"a": [[], {}, true, false, null, {"foo": "baz"}], "b": [1, 2.0, "three"]} ``` + the decoding APIs will be called with the following arguments: + ```erlang object_start(Acc0) => Acc1 string(<<"a">>) => Str1 @@ -341,11 +360,13 @@ object_finish(Acc18, Acc0) => {Obj3, Acc19} {Obj3, Acc19, <<"">>} ``` -### Example of a custom encoder +Example of a custom encoder +--------------------------- An example of a custom encoder that would support using a heuristic to differentiate pairs of object-like key-value lists from plain lists of values could look as follows: + ```erlang custom_encode(Value) -> json:encode(Value, fun encoder/2). @@ -355,6 +376,7 @@ encoder(Other, Encode) -> json:encode_value(Other, Encode). Another encoder that supports using Elixir `nil` as Null and protocols for further customisation could look as follows: + ```erlang encoder(nil, _Encode) -> <<"null">>; encoder(null, _Encode) -> <<"\"null\"">>; @@ -381,7 +403,8 @@ encoder(Other, Encode) -> json:encode_value(Other, Encode). [PR]: https://github.com/erlang/otp/pull/8111 -## Copyright +Copyright +========= This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.