Skip to content

Commit d7e93eb

Browse files
authored
Fix AbstractString key support for JSON.Object (#450)
1 parent a3f66e6 commit d7e93eb

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

src/object.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Base.isempty(obj::Object) = _k(obj) === notset && _ch(obj) === notset
121121
Base.empty(::Object{K,V}) where {K,V} = Object{K,V}() # empty object
122122

123123
# linear node lookup
124-
@inline function find_node_by_key(obj::Object{K,V}, key::K) where {K,V}
124+
@inline function find_node_by_key(obj::Object{K,V}, key) where {K,V}
125125
while true
126126
_k(obj) !== notset && isequal(_k(obj)::K, key) && return obj
127127
_ch(obj) === notset && break
@@ -142,9 +142,11 @@ Base.get(f::Base.Callable, obj::Object{Symbol}, key::String) = get(f, obj, Symbo
142142
Base.getindex(obj::Object, key) = get(() -> throw(KeyError(key)), obj, key)
143143
Base.getindex(obj::Object{String}, key::Symbol) = get(() -> throw(KeyError(key)), obj, String(key))
144144
Base.getindex(obj::Object{Symbol}, key::String) = get(() -> throw(KeyError(key)), obj, Symbol(key))
145-
Base.setindex!(obj::Object{String}, value, key::Symbol) = setindex!(obj, value, String(key))
145+
Base.setindex!(obj::Object{String,V}, value, key::AbstractString) where {V} = _setindex!(obj, value, String(key))
146+
Base.setindex!(obj::Object{String,V}, value, key::Symbol) where {V} = _setindex!(obj, value, String(key))
146147
Base.setindex!(obj::Object{Symbol}, value, key::String) = setindex!(obj, value, Symbol(key))
147-
Base.delete!(obj::Object{String}, key::Symbol) = delete!(obj, String(key))
148+
Base.delete!(obj::Object{String,V}, key::AbstractString) where {V} = _delete!(obj, String(key))
149+
Base.delete!(obj::Object{String,V}, key::Symbol) where {V} = _delete!(obj, String(key))
148150
Base.delete!(obj::Object{Symbol}, key::String) = delete!(obj, Symbol(key))
149151
Base.get(obj::Object, key, default) = get(() -> default, obj, key)
150152
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))
166168
Base.haskey(obj::Object{Symbol}, key::String) = haskey(obj, Symbol(key))
167169

168170
# setindex! finds node with key and sets value or inserts a new node
169-
function Base.setindex!(obj::Object{K,V}, value, key::K) where {K,V}
171+
function _setindex!(obj::Object{K,V}, value, key::K) where {K,V}
170172
root = obj
171173
while true
172174
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}
180182
Object{K,V}(obj, key, value)
181183
return value
182184
end
185+
Base.setindex!(obj::Object{K,V}, value, key::K) where {K,V} = _setindex!(obj, value, key)
183186

184187
# delete! removes node
185-
function Base.delete!(obj::Object{K,V}, key::K) where {K,V}
188+
function _delete!(obj::Object{K,V}, key::K) where {K,V}
186189
# check empty case
187190
_ch(obj) === notset && return obj
188191
root = parent = obj
@@ -204,6 +207,7 @@ function Base.delete!(obj::Object{K,V}, key::K) where {K,V}
204207
end
205208
return root
206209
end
210+
Base.delete!(obj::Object{K,V}, key::K) where {K,V} = _delete!(obj, key)
207211

208212
function Base.empty!(obj::Object)
209213
setfield!(obj, :child, notset)
@@ -214,4 +218,4 @@ end
214218
Base.setproperty!(obj::Object, sym::Symbol, val) = setindex!(obj, val, sym)
215219
Base.setproperty!(obj::Object{String}, sym::Symbol, val) = setindex!(obj, val, String(sym))
216220

217-
Base.merge(a::NamedTuple, b::Object{String,Any}) = merge(a, (Symbol(k) => v for (k, v) in b))
221+
Base.merge(a::NamedTuple, b::Object{String,Any}) = merge(a, (Symbol(k) => v for (k, v) in b))

test/object.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,25 @@ using JSON, Test
293293
@test !haskey(empty_obj, "anything")
294294
end
295295

296+
@testset "AbstractString key support for parsed String objects" begin
297+
obj = JSON.parse("{\"foo\": \"bar\"}")
298+
s = "abc.foo.xyz"
299+
k = split(s, ".")[2]
300+
301+
@test k isa SubString{String}
302+
@test haskey(obj, k)
303+
@test get(obj, k, nothing) == "bar"
304+
@test obj[k] == "bar"
305+
306+
obj[k] = "baz"
307+
@test obj["foo"] == "baz"
308+
309+
delete!(obj, k)
310+
@test !haskey(obj, "foo")
311+
@test get(obj, k, "default") == "default"
312+
@test_throws KeyError obj[k]
313+
end
314+
296315
# Test enhanced haskey for Symbol objects with String keys
297316
@testset "Enhanced haskey for Symbol Objects" begin
298317
obj = JSON.Object{Symbol, Any}()
@@ -404,4 +423,4 @@ using JSON, Test
404423
@test merged_mixed.float == 3.14
405424
@test merged_mixed.bool == true
406425
end
407-
end
426+
end

0 commit comments

Comments
 (0)