Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# njson

> **Archived**: This library is no longer maintained. Since OTP 27, the `json` module is included in the standard library and covers the same functionality. We recommend migrating to `json` for all new and existing projects. See the [Migration Guide](#migrating-to-otp-json) below.

[![njson](https://github.com/nomasystems/njson/actions/workflows/ci.yml/badge.svg)](https://github.com/nomasystems/njson/actions/workflows/ci.yml)

`njson` is a robust and efficient Erlang library that seamlessly encodes and decodes JSON
Expand Down Expand Up @@ -103,6 +106,95 @@ Encoder:
--------------------------------------------------------------------------------------
```

## Migrating to OTP json

OTP 27 introduced the `json` module, which provides native JSON encoding and decoding. This section covers the key differences and common pitfalls when migrating from `njson`.

### Decoding

`njson:decode/1` returns `{ok, Term}` or `{error, Reason}`. `json:decode/1` returns the term directly and throws on invalid input.

```erl
%% njson
{ok, Map} = njson:decode(Binary).

%% json
Map = json:decode(Binary).
```

If you relied on `{error, _}` to handle invalid JSON, wrap the call in a try-catch:

```erl
%% njson
case njson:decode(Binary) of
{ok, Map} -> handle(Map);
{error, _} -> handle_error()
end.

%% json
try json:decode(Binary) of
Map -> handle(Map)
catch
_:_ -> handle_error()
end.
```

### Encoding

`njson:encode/1` returns `{ok, Binary}`. `json:encode/1` returns **iodata** (not a binary).

```erl
%% njson
{ok, Binary} = njson:encode(Map).

%% json (returns iodata)
IoData = json:encode(Map).
```

If you need a `binary()`, wrap the result:

```erl
Binary = iolist_to_binary(json:encode(Map)).
```

If you are writing to a socket, file, or HTTP response body, iodata works directly and the conversion is unnecessary.

### Encoding differences

`json:encode/1` does not accept the atom `undefined`. It only handles `true`, `false`, and `null` as atom values. If your maps may contain `undefined` values, strip them before encoding:

```erl
strip_undefined(Map) when is_map(Map) ->
maps:filtermap(
fun
(_K, undefined) -> false;
(_K, V) when is_map(V) -> {true, strip_undefined(V)};
(_K, _V) -> true
end,
Map
).

json:encode(strip_undefined(MyMap)).
```

### Error handling summary

| Scenario | njson | json (OTP) |
| --- | --- | --- |
| Decode success | `{ok, Term}` | `Term` |
| Decode failure | `{error, Reason}` | Throws exception |
| Encode success | `{ok, Binary}` | `IoData` |
| Encode failure | `{error, Reason}` | Throws exception |

### Quick reference

| njson | json (OTP) | Notes |
| --- | --- | --- |
| `{ok, Map} = njson:decode(Bin)` | `Map = json:decode(Bin)` | Throws on invalid input |
| `{ok, Bin} = njson:encode(Map)` | `Bin = iolist_to_binary(json:encode(Map))` | Or use iodata directly |
| `{ok, IoList} = njson:encode(Map, true)` | `IoData = json:encode(Map)` | Already iodata |
| `case njson:decode(Bin) of {error,_} -> ...` | `try json:decode(Bin) catch _:_ -> ...` | Error handling |

## Support

Any doubt or suggestion? Please, check out [our issue tracker](https://github.com/nomasystems/njson/issues).