From 38eb70fc2654a10cdc5a8417ca1721b296f2ea76 Mon Sep 17 00:00:00 2001
From: piotr
Date: Tue, 22 Aug 2023 14:53:05 +0200
Subject: [PATCH 1/2] Added an option that allows encoding the Erlang's
`undefined` atom as a JSON `null`
---
README.md | 1 +
c_src/encoder.c | 9 +++++++++
c_src/jiffy.c | 2 ++
c_src/jiffy.h | 2 ++
src/jiffy.erl | 1 +
5 files changed, 15 insertions(+)
diff --git a/README.md b/README.md
index e28e2e8f..493c4c89 100644
--- a/README.md
+++ b/README.md
@@ -83,6 +83,7 @@ The options for encode are:
surrogate pairs and/or using the replacement character to remove
broken UTF-8 sequences in data.
* `use_nil` - Encodes the atom `nil` as `null`.
+* `use_undefined` - Encodes the atom `undefined` as `null`.
* `escape_forward_slashes` - Escapes the `/` character which can be
useful when encoding URLs in some cases.
* `{bytes_per_red, N}` - Refer to the decode options
diff --git a/c_src/encoder.c b/c_src/encoder.c
index 4cfb3533..3a4b3e44 100644
--- a/c_src/encoder.c
+++ b/c_src/encoder.c
@@ -34,6 +34,7 @@ typedef struct {
int uescape;
int pretty;
int use_nil;
+ int use_undefined;
int escape_forward_slashes;
int shiftcnt;
@@ -77,6 +78,7 @@ enc_new(ErlNifEnv* env)
e->uescape = 0;
e->pretty = 0;
e->use_nil = 0;
+ e->use_undefined = 0;
e->escape_forward_slashes = 0;
e->shiftcnt = 0;
e->count = 0;
@@ -677,6 +679,8 @@ encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
e->escape_forward_slashes = 1;
} else if(enif_is_identical(val, e->atoms->atom_use_nil)) {
e->use_nil = 1;
+ } else if(enif_is_identical(val, e->atoms->atom_use_undefined)) {
+ e->use_undefined = 1;
} else if(enif_is_identical(val, e->atoms->atom_force_utf8)) {
// Ignore, handled in Erlang
} else if(get_bytes_per_iter(env, val, &(e->bytes_per_red))) {
@@ -828,6 +832,11 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ret = enc_error(e, "null");
goto done;
}
+ } else if(e->use_undefined && enif_is_identical(curr, e->atoms->atom_undefined)) {
+ if(!enc_literal(e, "null", 4)) {
+ ret = enc_error(e, "null");
+ goto done;
+ }
} else if(enif_is_identical(curr, e->atoms->atom_true)) {
if(!enc_literal(e, "true", 4)) {
ret = enc_error(e, "true");
diff --git a/c_src/jiffy.c b/c_src/jiffy.c
index dfca7c70..78cbbade 100644
--- a/c_src/jiffy.c
+++ b/c_src/jiffy.c
@@ -14,6 +14,7 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
st->atom_ok = make_atom(env, "ok");
st->atom_error = make_atom(env, "error");
st->atom_null = make_atom(env, "null");
+ st->atom_undefined = make_atom(env, "undefined");
st->atom_true = make_atom(env, "true");
st->atom_false = make_atom(env, "false");
st->atom_bignum = make_atom(env, "bignum");
@@ -31,6 +32,7 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
st->atom_has_trailer = make_atom(env, "has_trailer");
st->atom_nil = make_atom(env, "nil");
st->atom_use_nil = make_atom(env, "use_nil");
+ st->atom_use_undefined = make_atom(env, "use_undefined");
st->atom_null_term = make_atom(env, "null_term");
st->atom_escape_forward_slashes = make_atom(env, "escape_forward_slashes");
st->atom_dedupe_keys = make_atom(env, "dedupe_keys");
diff --git a/c_src/jiffy.h b/c_src/jiffy.h
index 9c97945d..6f853a52 100644
--- a/c_src/jiffy.h
+++ b/c_src/jiffy.h
@@ -23,6 +23,7 @@ typedef struct {
ERL_NIF_TERM atom_ok;
ERL_NIF_TERM atom_error;
ERL_NIF_TERM atom_null;
+ ERL_NIF_TERM atom_undefined;
ERL_NIF_TERM atom_true;
ERL_NIF_TERM atom_false;
ERL_NIF_TERM atom_bignum;
@@ -40,6 +41,7 @@ typedef struct {
ERL_NIF_TERM atom_has_trailer;
ERL_NIF_TERM atom_nil;
ERL_NIF_TERM atom_use_nil;
+ ERL_NIF_TERM atom_use_undefined;
ERL_NIF_TERM atom_null_term;
ERL_NIF_TERM atom_escape_forward_slashes;
ERL_NIF_TERM atom_dedupe_keys;
diff --git a/src/jiffy.erl b/src/jiffy.erl
index 6af15b5f..455500c6 100644
--- a/src/jiffy.erl
+++ b/src/jiffy.erl
@@ -49,6 +49,7 @@
| pretty
| force_utf8
| use_nil
+ | use_undefined
| escape_forward_slashes
| {bytes_per_iter, non_neg_integer()}
| {bytes_per_red, non_neg_integer()}.
From c072711e03095ad5e560c25c845af449a2a3d8b2 Mon Sep 17 00:00:00 2001
From: piotr
Date: Tue, 22 Aug 2023 14:53:59 +0200
Subject: [PATCH 2/2] undefined to null conversion test case
---
test/jiffy_02_literal_tests.erl | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/test/jiffy_02_literal_tests.erl b/test/jiffy_02_literal_tests.erl
index 5a6a17fb..1d92c2b3 100644
--- a/test/jiffy_02_literal_tests.erl
+++ b/test/jiffy_02_literal_tests.erl
@@ -33,6 +33,12 @@ nil_test_() ->
{"Encode", ?_assertEqual(<<"null">>, enc(nil, [use_nil]))}
]}.
+undefined_test_() ->
+ {"undefined", [
+ {"Decode", ?_assertEqual(undefined, dec(<<"null">>, [{null_term, undefined}]))},
+ {"Encode", ?_assertEqual(<<"null">>, enc(undefined, [use_undefined]))}
+ ]}.
+
null_term_test_() ->
T = [
{undefined, [{null_term, undefined}]},