Skip to content

Commit

Permalink
Merge pull request #5 from LoyaltyNZ/feature/fix-nested-nil
Browse files Browse the repository at this point in the history
Cope gracefully with errors when path contains a nil value
  • Loading branch information
odogono authored Jul 31, 2019
2 parents 50c00dd + 00858bd commit 36c1fa1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: elixir
elixir:
- 1.6
- 1.8
- 1.9
otp_release:
- 19.3
- 20.2
- 22.0
sudo: false
26 changes: 26 additions & 0 deletions lib/json_pointer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ defmodule JSONPointer do
iex> JSONPointer.get( %{ "contents" => [ "milk", "butter", "eggs" ]}, "/contents/4" )
{:error, "index out of bounds: 4"}
iex> JSONPointer.get( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake" )
{:error, "parent token not found: cake"}
"""
@spec get(container, pointer) :: {:ok, t} | error_message
def get(obj, pointer, options \\ @default_options) do
Expand All @@ -98,6 +103,10 @@ defmodule JSONPointer do
true
iex> JSONPointer.get!( %{}, "/fridge/milk" )
** (ArgumentError) json pointer key not found: fridge
iex> JSONPointer.get!( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake" )
** (ArgumentError) parent token not found: cake
"""
@spec get!(container, pointer, options) :: t | no_return
def get!(obj, pointer, options \\ @default_options) do
Expand All @@ -116,6 +125,9 @@ defmodule JSONPointer do
iex> JSONPointer.has?( %{ "milk" => true, "butter" => false}, "/cornflakes" )
false
iex> JSONPointer.has?( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake" )
false
"""
@spec has?(container, pointer, options) :: boolean
def has?(obj, pointer, options \\ @default_options) do
Expand All @@ -132,6 +144,8 @@ defmodule JSONPointer do
iex> JSONPointer.test( %{ "milk" => "skimmed", "butter" => false}, "/milk", "skimmed" )
{:ok, %{ "milk" => "skimmed", "butter" => false} }
iex> JSONPointer.test( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake", "true" )
{:error, "parent token not found: cake"}
"""
@spec test(container, pointer, t, options) :: {:ok, t} | error_message
def test(obj, pointer, value, options \\ @default_options) do
Expand All @@ -154,6 +168,9 @@ defmodule JSONPointer do
iex> JSONPointer.test!( %{ "milk" => "skimmed", "butter" => false}, "/butter", "unsalted" )
** (ArgumentError) not equal
iex> JSONPointer.test!( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake", "true" )
** (ArgumentError) parent token not found: cake
"""
@spec test!(container, pointer, t, options) :: t | no_return
def test!(obj, pointer, value, options \\ @default_options) do
Expand All @@ -172,6 +189,9 @@ defmodule JSONPointer do
iex> JSONPointer.remove( %{"fridge" => %{ "milk" => true, "butter" => true}}, "/fridge/sandwich" )
{:error, "json pointer key not found: sandwich", %{ "butter" => true, "milk" => true}}
iex> JSONPointer.remove( %{ "fridge" => %{ "cake" => true }, "stove" => nil}, "/stove/cake" )
{:error, "parent token not found: cake", nil}
"""
@spec remove(container, pointer, options) :: {:ok, t, removed} | error_message
def remove(object, pointer, options \\ @default_options) do
Expand All @@ -190,6 +210,7 @@ defmodule JSONPointer do
iex> JSONPointer.set( %{"milk"=>"full"}, "/milk", "empty")
{:ok, %{"milk" => "empty"}, "full"}
"""
@spec set(container, pointer, t, options) :: {:ok, t, existing} | error_message
def set(obj, pointer, value, options \\ @default_options) do
Expand Down Expand Up @@ -921,6 +942,11 @@ defmodule JSONPointer do
{:ok, result, nil}
end

# stop walking the container if we hit a nil value
defp walk_container(_operation, _parent, nil, token, _tokens, _value, _options) do
{:error, "parent token not found: #{token}", nil}
end

defp next_result(
{:ok, _existing},
operation,
Expand Down

0 comments on commit 36c1fa1

Please sign in to comment.