""" Recursively convert dictionary-like variable (e.g. JSON.Object) into a dictionary. The function walks any nested structure composed of `AbstractDict` (e.g., `JSON.Object`, `Dict`, `OrderedDict`) and `AbstractArray` and produces a new tree where every dictionary-like node is a plain `Dict` and every array-like node is a `Vector{Any}`. Scalar values (numbers, strings, booleans, `nothing`, etc.) are returned unchanged. Does **not** mutate the input; it always allocates new containers. # Arguments - `x` Any Julia value. If `x` is an `AbstractDict` it will be converted to a `Dict`; if it is an `AbstractArray` its elements will be processed recursively. # Keyword Arguments - `keytype::Type=Any` The key type for the output Dict. Use `String` for `Dict{String,Any}`, `Symbol` for `Dict{Symbol,Any}`, or `Any` to preserve original key types. - `stringkey::Bool=false` If `true`, every dictionary key is converted to `String` via `string(k)`. This parameter is ignored when `keytype` is explicitly set. # Return - A newly allocated nested structure composed of `Dict{keytype,Any}` and `Vector{Any}` that mirrors the input shape but uses plain Julia containers. # Notes - The function treats any `AbstractDict` as a mapping source, so it works with `JSON.Object`, `Dict`, `OrderedDict`, etc. - Arrays are returned as `Vector{Any}` with their elements processed recursively. # Examples ```jldoctest julia> using JSON julia> d = Dict( "a" => 4, "b" => 6, "c" => Dict( "d"=>7, :e=>Dict( "f"=>"hey", "g"=>Dict( "world"=>[1, "2", 3, Dict(:dd=>4.7)] ) ) ) ) julia jsonstring = JSON.json(d) julia> A1 = JSON.parse(jsonstring) # A1 type is JSON.Object julia> A2 = dictify(A1; keytype=String) Dict{String,Any} with 3 entries: "a" => 4 "b" => 6 "c" => Dict("d"=>7, "e"=>Dict("f"=>"hey", "g"=>Dict("world"=>[1, "2", 3, 4.7]))) julia> A3 = dictify(A1; keytype=Symbol) Dict{Symbol,Any} with 3 entries: :a => 4 :b => 6 :c => Dict(:d=>7, :e=>Dict("f"=>"hey", "g"=>Dict("world"=>[1, "2", 3, 4.7]))) julia> B1 = dictify(d; keytype=String) Dict{String, Any} with 3 entries: """ function dictify(x; keytype::Type=Any) # Dict-like objects if x isa AbstractDict # choose output key type container out = Dict{keytype,Any}() for (k,v) in x if keytype === String newk = string(k) elseif keytype === Symbol newk = Symbol(string(k)) else newk = k end out[newk] = dictify(v; keytype=keytype) end return out # Arrays / vectors: map elements recursively and return a Vector{Any} elseif x isa AbstractArray return [dictify(element; keytype=keytype) for element in x] # everything else: return as-is (primitives, numbers, strings, etc.) else return x end end