From 41b4220518061afac53c2a51e55de9c06fee31b7 Mon Sep 17 00:00:00 2001 From: Nicholas Lundgaard Date: Tue, 29 Mar 2022 08:49:08 -0500 Subject: [PATCH] Patch jsn:delete to delete objects at end of path Resolves #42. **Problem** when calling `jsn:delete/2` on a path to an object where the value is itself an object, `jsn` doesn't delete the object due to incorrect guards in the handling of deletion for nested paths: the guard does not work when there *isn't* a nested path element to walk into, leaving the leaf object. **Solution** Fix the guard and update the tests. --- src/jsn.erl | 3 ++- test/jsn_tests.erl | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/jsn.erl b/src/jsn.erl index 393a1c3..2927dfe 100644 --- a/src/jsn.erl +++ b/src/jsn.erl @@ -989,7 +989,8 @@ keys_set(Keys, {P}, Value, Empty) when is_list(P) -> keys_set([Key | Rest], Object, Value, Empty) when is_binary(Key), (is_list(Object) orelse is_map(Object)) -> case key_get(Key, Object, jsn__undefined) of - E when Value =:= jsn__delete, (E =:= jsn__undefined orelse E =:= Empty) -> + E when Value =:= jsn__delete, Rest /= [], + (E =:= jsn__undefined orelse E =:= Empty) -> return_if_object(Object, Empty); E when E =:= jsn__undefined; E =:= Empty -> key_set(Key, Object, keys_set(Rest, Empty, Value, Empty)); diff --git a/test/jsn_tests.erl b/test/jsn_tests.erl index 6797a9b..a707b26 100644 --- a/test/jsn_tests.erl +++ b/test/jsn_tests.erl @@ -295,6 +295,12 @@ delete_test_() -> ?_assertEqual(#{}, jsn:delete(Path3, #{})), ?_assertEqual([], jsn:delete(<<"foo">>, [{<<"foo">>, <<"bar">>}])), ?_assertEqual(#{}, jsn:delete(<<"foo">>, #{<<"foo">> => <<"bar">>})), + ?_assertEqual(#{}, jsn:delete(<<"foo">>, #{<<"foo">> => #{}})), + ?_assertEqual(#{}, jsn:delete(<<"foo">>, #{<<"foo">> => []})), + ?_assertEqual(#{<<"foo">> => #{}}, + jsn:delete(<<"foo.bar">>, #{<<"foo">> => #{<<"bar">> => #{}}})), + ?_assertEqual(#{<<"foo">> => #{<<"bar">> => #{}}}, + jsn:delete(<<"foo.baz">>, #{<<"foo">> => #{<<"bar">> => #{}}})), ?_assertEqual(jsn:new({Path2, [1,2,3]}, [{format, proplist}]), jsn:delete(foo, Object1Plist)), ?_assertEqual(jsn:new({Path2, [1,2,3]}, [{format, map}]),