Skip to content

Commit

Permalink
Formatting fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
michalmuskala committed Feb 20, 2024
1 parent 064402c commit 4c8e3ca
Showing 1 changed file with 37 additions and 14 deletions.
51 changes: 37 additions & 14 deletions eeps/eep-0068.md
Expand Up @@ -5,20 +5,23 @@
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
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;
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -128,6 +136,7 @@ First, a simple, value-based API:

Error handling is achieved through exceptions. The following errors
are possible:

```erlang

Check failure on line 140 in eeps/eep-0068.md

View workflow job for this annotation

GitHub Actions / markdownlint

Code block style

eeps/eep-0068.md:140 MD046/code-block-style Code block style [Expected: indented; Actual: fenced] https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md046.md
-type error() ::
unexpected_end |
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -268,7 +280,8 @@ that will always produce purely ASCII messages encoding all higher
unicode values with the `\u` escape sequences.


Check failure on line 282 in eeps/eep-0068.md

View workflow job for this annotation

GitHub Actions / markdownlint

Multiple consecutive blank lines

eeps/eep-0068.md:282 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md012.md
### 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
Expand All @@ -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

Check failure on line 322 in eeps/eep-0068.md

View workflow job for this annotation

GitHub Actions / markdownlint

Code block style

eeps/eep-0068.md:322 MD046/code-block-style Code block style [Expected: indented; Actual: fenced] https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md046.md
{"a": [[], {}, true, false, null, {"foo": "baz"}], "b": [1, 2.0, "three"]}
```
the decoding APIs will be called with the following arguments:
```erlang

Check failure on line 328 in eeps/eep-0068.md

View workflow job for this annotation

GitHub Actions / markdownlint

Code block style

eeps/eep-0068.md:328 MD046/code-block-style Code block style [Expected: indented; Actual: fenced] https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md046.md
object_start(Acc0) => Acc1
string(<<"a">>) => Str1
Expand Down Expand Up @@ -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).
Expand All @@ -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\"">>;
Expand All @@ -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.

0 comments on commit 4c8e3ca

Please sign in to comment.