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}]},