@@ -174,9 +174,12 @@ StructUtils.fieldtagkey(::JSONStyle) = :json
174174StructUtils. defaultstate (st:: JSONReadStyle ) = StructUtils. defaultstate (st. style)
175175
176176# forward StructUtils API to the inner style so user-provided JSONStyle dispatches are honored
177- StructUtils. dictlike (st:: JSONReadStyle , :: Type{T} ) where {T} = StructUtils. dictlike (st. style, T)
178- StructUtils. arraylike (st:: JSONReadStyle , :: Type{T} ) where {T} = StructUtils. arraylike (st. style, T)
179- StructUtils. nulllike (st:: JSONReadStyle , :: Type{T} ) where {T} = StructUtils. nulllike (st. style, T)
177+ StructUtils. dictlike (st:: JSONReadStyle{O,N,S} , :: Type{T} ) where {O,N,S<: JSONStyle ,T} =
178+ StructUtils. dictlike (st. style, T)
179+ StructUtils. arraylike (st:: JSONReadStyle{O,N,S} , :: Type{T} ) where {O,N,S<: JSONStyle ,T} =
180+ StructUtils. arraylike (st. style, T)
181+ StructUtils. nulllike (st:: JSONReadStyle{O,N,S} , :: Type{T} ) where {O,N,S<: JSONStyle ,T} =
182+ StructUtils. nulllike (st. style, T)
180183# Keep structlike forwarding specific to custom JSONStyle wrappers so type-level StructStyle
181184# specializations (for example @nonstruct types) continue to dispatch without ambiguity.
182185StructUtils. structlike (st:: JSONReadStyle{O,N,S} , :: Type{T} ) where {O,N,S<: JSONStyle ,T} =
@@ -192,6 +195,12 @@ function jsonreadstyle(::Type{T}, ::Type{O}, null, style::StructStyle, unknown_f
192195 if T === Any && ! ignore_unknown_fields
193196 throw (ArgumentError (" `unknown_fields` is only supported when parsing into a target type or existing object" ))
194197 end
198+ # Avoid wrapping aggregate targets whose broad style methods would otherwise
199+ # become ambiguous with JSONReadStyle's custom-style forwarding.
200+ if O === DEFAULT_OBJECT_TYPE && null === nothing && ignore_unknown_fields && style isa JSONStyle &&
201+ (StructUtils. dictlike (style, T) || StructUtils. arraylike (style, T) || StructUtils. nulllike (style, T))
202+ return style
203+ end
195204 return JSONReadStyle {O} (null, style, ignore_unknown_fields)
196205end
197206
@@ -377,17 +386,23 @@ function StructUtils.make(st::StructStyle, ::Type{Any}, x::LazyValues)
377386end
378387
379388# catch PtrString via lift or make! so we can ensure it never "escapes" to user-level
389+ StructUtils. liftkey (st:: JSONStyle , :: Type{T} , x:: PtrString ) where {T} =
390+ StructUtils. liftkey (st, T, convert (String, x))
380391StructUtils. liftkey (st:: JSONReadStyle , :: Type{T} , x:: PtrString ) where {T} =
381392 StructUtils. liftkey (st, T, convert (String, x))
393+ StructUtils. lift (st:: JSONStyle , :: Type{T} , x:: PtrString , tags) where {T} =
394+ StructUtils. lift (st, T, convert (String, x), tags)
382395StructUtils. lift (st:: JSONReadStyle , :: Type{T} , x:: PtrString , tags) where {T} =
383396 StructUtils. lift (st, T, convert (String, x), tags)
397+ StructUtils. lift (st:: JSONStyle , :: Type{T} , x:: PtrString ) where {T} =
398+ StructUtils. lift (st, T, convert (String, x))
384399StructUtils. lift (st:: JSONReadStyle , :: Type{T} , x:: PtrString ) where {T} =
385400 StructUtils. lift (st, T, convert (String, x))
386401
387402# liftkey for numeric dict key types to enable round-tripping Dict{Int,V}, Dict{Float64,V}, etc.
388403# these correspond to the lowerkey definitions in write.jl that convert numeric keys to strings
389- StructUtils. liftkey (:: JSONReadStyle , :: Type{T} , x:: AbstractString ) where {T<: Integer } = Base. parse (T, x)
390- StructUtils. liftkey (:: JSONReadStyle , :: Type{T} , x:: AbstractString ) where {T<: AbstractFloat } = Base. parse (T, x)
404+ StructUtils. liftkey (:: JSONStyle , :: Type{T} , x:: AbstractString ) where {T<: Integer } = Base. parse (T, x)
405+ StructUtils. liftkey (:: JSONStyle , :: Type{T} , x:: AbstractString ) where {T<: AbstractFloat } = Base. parse (T, x)
391406
392407_isliftpair (x) = x isa Tuple && ! (x isa NamedTuple) && length (x) == 2
393408_liftresult (x, st) = _isliftpair (x) ? x : (x, StructUtils. defaultstate (st))
@@ -396,8 +411,10 @@ _liftresult(x, pos::Int) = _isliftpair(x) ? x : (x, pos)
396411struct _NoCustomLazyLift end
397412const _NO_CUSTOM_LAZY_LIFT = _NoCustomLazyLift ()
398413
399- StructUtils. lift (:: JSONStyle , :: Type{T} , :: LazyValues , tags) where {T} = _NO_CUSTOM_LAZY_LIFT
400- StructUtils. lift (:: JSONStyle , :: Type{T} , :: LazyValues ) where {T} = _NO_CUSTOM_LAZY_LIFT
414+ StructUtils. lift (style:: JSONStyle , :: Type{T} , x:: LazyValues , tags) where {T} =
415+ _maybeliftjsonvalue (style, T, x, tags)
416+ StructUtils. lift (style:: JSONStyle , :: Type{T} , x:: LazyValues ) where {T} =
417+ _maybeliftjsonvalue (style, T, x, (;))
401418
402419StructUtils. lift (style:: JSONReadStyle , :: Type{T} , x, tags) where {T} =
403420 _liftresult (StructUtils. lift (style. style, T, x, tags), style)
@@ -414,13 +431,32 @@ function customlazylift(style::JSONReadStyle, ::Type{T}, x::LazyValues, tags) wh
414431 return nothing
415432end
416433
434+ function StructUtils. lift (style:: JSONStyle , :: Type{T} , x:: LazyValues ) where {T<: AbstractArray{E,0} } where {E}
435+ m = T (undef)
436+ m[1 ], pos = StructUtils. lift (style, E, x)
437+ return m, pos
438+ end
439+
417440function StructUtils. lift (style:: JSONReadStyle , :: Type{T} , x:: LazyValues ) where {T<: AbstractArray{E,0} } where {E}
418441 m = T (undef)
419442 m[1 ], pos = StructUtils. lift (style, E, x)
420443 return m, pos
421444end
422445
423- function StructUtils. lift (style:: JSONReadStyle , :: Type{T} , x:: LazyValues , tags= (;)) where {T}
446+ StructUtils. lift (style:: JSONReadStyle , :: Type{T} , x:: LazyValues , tags) where {T} =
447+ _liftjsonvalue (style, T, x, tags)
448+ StructUtils. lift (style:: JSONReadStyle , :: Type{T} , x:: LazyValues ) where {T} =
449+ _liftjsonvalue (style, T, x, (;))
450+
451+ function _maybeliftjsonvalue (style:: JSONStyle , :: Type{T} , x:: LazyValues , tags) where {T}
452+ type = gettype (x)
453+ if type == JSONTypes. OBJECT || type == JSONTypes. ARRAY
454+ return _NO_CUSTOM_LAZY_LIFT
455+ end
456+ return _liftjsonvalue (style, T, x, tags)
457+ end
458+
459+ function _liftjsonvalue (style:: JSONStyle , :: Type{T} , x:: LazyValues , tags) where {T}
424460 type = gettype (x)
425461 buf = getbuf (x)
426462 if type == JSONTypes. OBJECT || type == JSONTypes. ARRAY
0 commit comments