diff --git a/src/parse.jl b/src/parse.jl index 26ea951..1a4745a 100644 --- a/src/parse.jl +++ b/src/parse.jl @@ -171,6 +171,11 @@ nullvalue(st::JSONReadStyle) = st.null StructUtils.fieldtagkey(::JSONStyle) = :json StructUtils.defaultstate(st::JSONReadStyle) = StructUtils.defaultstate(st.style) +# forward StructUtils API to the inner style so user-provided JSONStyle dispatches are honored +StructUtils.dictlike(st::JSONReadStyle, ::Type{T}) where {T} = StructUtils.dictlike(st.style, T) +StructUtils.arraylike(st::JSONReadStyle, ::Type{T}) where {T} = StructUtils.arraylike(st.style, T) +StructUtils.nulllike(st::JSONReadStyle, ::Type{T}) where {T} = StructUtils.nulllike(st.style, T) + function jsonreadstyle(::Type{T}, ::Type{O}, null, style::StructStyle, unknown_fields::Symbol) where {T,O} ignore_unknown_fields = unknown_fields === :ignore ? true : diff --git a/test/parse.jl b/test/parse.jl index 3347bee..172fb0e 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -227,6 +227,15 @@ end any::Any &(choosetype=x -> x.type[] == "int" ? @NamedTuple{type::String, value::Int} : x.type[] == "float" ? @NamedTuple{type::String, value::Float64} : @NamedTuple{type::String, value::String},) end +# https://github.com/JuliaIO/JSON.jl/issues/453 - custom JSONStyle dictlike dispatch +@kwdef struct DictlikeViaCustomStyle + vals::Dict{String,Int} = Dict{String,Int}() +end +Base.keytype(::DictlikeViaCustomStyle) = String +Base.valtype(::DictlikeViaCustomStyle) = Int +StructUtils.addkeyval!(a::DictlikeViaCustomStyle, k, v) = StructUtils.addkeyval!(a.vals, k, v) +StructUtils.dictlike(::CustomJSONStyle, ::Type{DictlikeViaCustomStyle}) = true + @testset "JSON.parse" begin @testset "errors" begin # Unexpected character in array @@ -765,6 +774,10 @@ end JSON.lift(::CustomJSONStyle, ::Type{Rational}, x) = Rational(x.num[], x.den[]) @test JSON.parse("{\"num\": 1,\"den\":3}", Rational; style=CustomJSONStyle()) == 1//3 @test JSON.parse("{\"num\": 1,\"den\":3}", Rational; style=CustomJSONStyle(), unknown_fields=:error) == 1//3 + # https://github.com/JuliaIO/JSON.jl/issues/453 - dictlike dispatch on custom JSONStyle must reach user method + let res = JSON.parse("""{"a": 1, "b": 2}""", DictlikeViaCustomStyle; style=CustomJSONStyle()) + @test res.vals == Dict("a" => 1, "b" => 2) + end @test isequal(JSON.parse("{\"num\": 1,\"den\":null}", @NamedTuple{num::Int, den::Union{Int, Missing}}; null=missing, style=StructUtils.DefaultStyle()), (num=1, den=missing)) # choosetype field tag on Any struct field @test JSON.parse("{\"id\":1,\"any\":{\"type\":\"int\",\"value\":10}}", Q) == Q(1, (type="int", value=10))