diff --git a/src/object.jl b/src/object.jl index 24bb66d..70ba246 100644 --- a/src/object.jl +++ b/src/object.jl @@ -121,7 +121,7 @@ Base.isempty(obj::Object) = _k(obj) === notset && _ch(obj) === notset Base.empty(::Object{K,V}) where {K,V} = Object{K,V}() # empty object # linear node lookup -@inline function find_node_by_key(obj::Object{K,V}, key::K) where {K,V} +@inline function find_node_by_key(obj::Object{K,V}, key) where {K,V} while true _k(obj) !== notset && isequal(_k(obj)::K, key) && return obj _ch(obj) === notset && break @@ -142,9 +142,11 @@ Base.get(f::Base.Callable, obj::Object{Symbol}, key::String) = get(f, obj, Symbo Base.getindex(obj::Object, key) = get(() -> throw(KeyError(key)), obj, key) Base.getindex(obj::Object{String}, key::Symbol) = get(() -> throw(KeyError(key)), obj, String(key)) Base.getindex(obj::Object{Symbol}, key::String) = get(() -> throw(KeyError(key)), obj, Symbol(key)) -Base.setindex!(obj::Object{String}, value, key::Symbol) = setindex!(obj, value, String(key)) +Base.setindex!(obj::Object{String,V}, value, key::AbstractString) where {V} = _setindex!(obj, value, String(key)) +Base.setindex!(obj::Object{String,V}, value, key::Symbol) where {V} = _setindex!(obj, value, String(key)) Base.setindex!(obj::Object{Symbol}, value, key::String) = setindex!(obj, value, Symbol(key)) -Base.delete!(obj::Object{String}, key::Symbol) = delete!(obj, String(key)) +Base.delete!(obj::Object{String,V}, key::AbstractString) where {V} = _delete!(obj, String(key)) +Base.delete!(obj::Object{String,V}, key::Symbol) where {V} = _delete!(obj, String(key)) Base.delete!(obj::Object{Symbol}, key::String) = delete!(obj, Symbol(key)) Base.get(obj::Object, key, default) = get(() -> default, obj, key) Base.get(obj::Object{String}, key::Symbol, default) = get(obj, String(key), default) @@ -166,7 +168,7 @@ Base.haskey(obj::Object{String}, key::Symbol) = haskey(obj, String(key)) Base.haskey(obj::Object{Symbol}, key::String) = haskey(obj, Symbol(key)) # setindex! finds node with key and sets value or inserts a new node -function Base.setindex!(obj::Object{K,V}, value, key::K) where {K,V} +function _setindex!(obj::Object{K,V}, value, key::K) where {K,V} root = obj while true if _k(obj) !== notset && isequal(_k(obj)::K, key) @@ -180,9 +182,10 @@ function Base.setindex!(obj::Object{K,V}, value, key::K) where {K,V} Object{K,V}(obj, key, value) return value end +Base.setindex!(obj::Object{K,V}, value, key::K) where {K,V} = _setindex!(obj, value, key) # delete! removes node -function Base.delete!(obj::Object{K,V}, key::K) where {K,V} +function _delete!(obj::Object{K,V}, key::K) where {K,V} # check empty case _ch(obj) === notset && return obj root = parent = obj @@ -204,6 +207,7 @@ function Base.delete!(obj::Object{K,V}, key::K) where {K,V} end return root end +Base.delete!(obj::Object{K,V}, key::K) where {K,V} = _delete!(obj, key) function Base.empty!(obj::Object) setfield!(obj, :child, notset) @@ -214,4 +218,4 @@ end Base.setproperty!(obj::Object, sym::Symbol, val) = setindex!(obj, val, sym) Base.setproperty!(obj::Object{String}, sym::Symbol, val) = setindex!(obj, val, String(sym)) -Base.merge(a::NamedTuple, b::Object{String,Any}) = merge(a, (Symbol(k) => v for (k, v) in b)) \ No newline at end of file +Base.merge(a::NamedTuple, b::Object{String,Any}) = merge(a, (Symbol(k) => v for (k, v) in b)) diff --git a/test/object.jl b/test/object.jl index a9d826f..d691db0 100644 --- a/test/object.jl +++ b/test/object.jl @@ -293,6 +293,25 @@ using JSON, Test @test !haskey(empty_obj, "anything") end + @testset "AbstractString key support for parsed String objects" begin + obj = JSON.parse("{\"foo\": \"bar\"}") + s = "abc.foo.xyz" + k = split(s, ".")[2] + + @test k isa SubString{String} + @test haskey(obj, k) + @test get(obj, k, nothing) == "bar" + @test obj[k] == "bar" + + obj[k] = "baz" + @test obj["foo"] == "baz" + + delete!(obj, k) + @test !haskey(obj, "foo") + @test get(obj, k, "default") == "default" + @test_throws KeyError obj[k] + end + # Test enhanced haskey for Symbol objects with String keys @testset "Enhanced haskey for Symbol Objects" begin obj = JSON.Object{Symbol, Any}() @@ -404,4 +423,4 @@ using JSON, Test @test merged_mixed.float == 3.14 @test merged_mixed.bool == true end -end \ No newline at end of file +end