fix dictify
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name = "GeneralUtils"
|
name = "GeneralUtils"
|
||||||
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
|
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|||||||
+100
-12
@@ -204,33 +204,43 @@ end
|
|||||||
|
|
||||||
|
|
||||||
""" Recursively convert dictionary-like variable (e.g. JSON.Object) into a dictionary.
|
""" Recursively convert dictionary-like variable (e.g. JSON.Object) into a dictionary.
|
||||||
|
|
||||||
|
Two methods are available:
|
||||||
|
|
||||||
|
**Method 1** (simple): Converts `AbstractDict` to `Dict` and `AbstractArray` to `Vector{Any}`.
|
||||||
|
|
||||||
|
**Method 2** (advanced): Also accepts a `sort_order` keyword argument to control key ordering
|
||||||
|
in the output `OrderedDict`. When `sort_order` is specified, the function returns an `OrderedDict`
|
||||||
|
with keys arranged according to the provided order, followed by any remaining keys.
|
||||||
|
|
||||||
The function walks any nested structure composed of `AbstractDict` (e.g., `JSON.Object`,
|
The function walks any nested structure composed of `AbstractDict` (e.g., `JSON.Object`,
|
||||||
`Dict`, `OrderedDict`) and `AbstractArray` and produces a new tree where
|
`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
|
every dictionary-like node is a plain `Dict` (or `OrderedDict` when `sort_order` is used)
|
||||||
`Vector{Any}`. Scalar values (numbers, strings, booleans, `nothing`, etc.)
|
and every array-like node is a `Vector{Any}`. Scalar values (numbers, strings, booleans,
|
||||||
are returned unchanged.
|
`nothing`, etc.) are returned unchanged.
|
||||||
Does **not** mutate the input; it always allocates new containers.
|
Does **not** mutate the input; it always allocates new containers.
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
- `x`
|
- `x`
|
||||||
Any Julia value. If `x` is an `AbstractDict` it will be converted to a `Dict`;
|
Any Julia value. If `x` is an `AbstractDict` it will be converted to a `Dict` (or `OrderedDict`);
|
||||||
if it is an `AbstractArray` its elements will be processed recursively.
|
if it is an `AbstractArray` its elements will be processed recursively.
|
||||||
|
|
||||||
# Keyword Arguments
|
# Keyword Arguments
|
||||||
- `keytype::Type=Any`
|
- `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.
|
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`
|
- `sort_order::Union{Nothing, Vector}=nothing` (Method 2 only)
|
||||||
If `true`, every dictionary key is converted to `String` via `string(k)`. This parameter is ignored when `keytype` is explicitly set.
|
Vector of keys specifying the desired order. When provided, output uses `OrderedDict` with
|
||||||
|
keys arranged in the specified order first, then any remaining keys appended.
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
- A newly allocated nested structure composed of `Dict{keytype,Any}` and
|
- A newly allocated nested structure composed of `Dict{keytype,Any}` (or `OrderedDict{keytype,Any}`
|
||||||
`Vector{Any}` that mirrors the input shape but uses plain Julia containers.
|
when `sort_order` is specified) and `Vector{Any}` that mirrors the input shape but uses plain Julia containers.
|
||||||
|
|
||||||
# Notes
|
# Notes
|
||||||
- The function treats any `AbstractDict` as a mapping source, so it works with
|
- The function treats any `AbstractDict` as a mapping source, so it works with
|
||||||
`JSON.Object`, `Dict`, `OrderedDict`, etc.
|
`JSON.Object`, `Dict`, `OrderedDict`, etc.
|
||||||
- Arrays are returned as `Vector{Any}` with their elements processed
|
- Arrays are returned as `Vector{Any}` with their elements processed recursively.
|
||||||
recursively.
|
- When `sort_order` is provided, the function uses `OrderedDict` to preserve key ordering.
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
```jldoctest
|
```jldoctest
|
||||||
@@ -249,7 +259,7 @@ julia> d = Dict(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
julia jsonstring = JSON.json(d)
|
julia> jsonstring = JSON.json(d)
|
||||||
julia> A1 = JSON.parse(jsonstring) # A1 type is JSON.Object
|
julia> A1 = JSON.parse(jsonstring) # A1 type is JSON.Object
|
||||||
julia> A2 = dictify(A1; keytype=String)
|
julia> A2 = dictify(A1; keytype=String)
|
||||||
Dict{String,Any} with 3 entries:
|
Dict{String,Any} with 3 entries:
|
||||||
@@ -265,6 +275,17 @@ Dict{Symbol,Any} with 3 entries:
|
|||||||
|
|
||||||
julia> B1 = dictify(d; keytype=String)
|
julia> B1 = dictify(d; keytype=String)
|
||||||
Dict{String, Any} with 3 entries:
|
Dict{String, Any} with 3 entries:
|
||||||
|
```
|
||||||
|
|
||||||
|
**With sort_order (returns OrderedDict):**
|
||||||
|
```jldoctest
|
||||||
|
julia> d = Dict("a"=>1, "b"=>2, "c"=>3)
|
||||||
|
julia> dictify(d; sort_order=["c", "a"])
|
||||||
|
OrderedDict{String,Int} with 3 entries:
|
||||||
|
"c" => 3
|
||||||
|
"a" => 1
|
||||||
|
"b" => 2
|
||||||
|
```
|
||||||
"""
|
"""
|
||||||
function dictify(x; keytype::Type=Any)
|
function dictify(x; keytype::Type=Any)
|
||||||
# Dict-like objects
|
# Dict-like objects
|
||||||
@@ -291,6 +312,68 @@ function dictify(x; keytype::Type=Any)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dictify(x; keytype::Type=Any, sort_order::Union{Nothing, Vector}=nothing)
|
||||||
|
# Dict-like objects
|
||||||
|
if x isa AbstractDict
|
||||||
|
out = OrderedDict{keytype, Any}()
|
||||||
|
|
||||||
|
# 1. Process and normalize all keys from the input dictionary
|
||||||
|
processed_dict = OrderedDict{keytype, Any}()
|
||||||
|
for (k, v) in x
|
||||||
|
if keytype === String
|
||||||
|
newk = string(k)
|
||||||
|
elseif keytype === Symbol
|
||||||
|
newk = Symbol(string(k))
|
||||||
|
else
|
||||||
|
newk = k
|
||||||
|
end
|
||||||
|
processed_dict[newk] = dictify(v; keytype=keytype, sort_order=sort_order)
|
||||||
|
end
|
||||||
|
|
||||||
|
# 2. If a sort order is specified, apply it
|
||||||
|
if !isnothing(sort_order)
|
||||||
|
# Normalize the sort_order elements to match the requested keytype
|
||||||
|
normalized_order = map(sort_order) do tk
|
||||||
|
if keytype === String
|
||||||
|
return string(tk)
|
||||||
|
elseif keytype === Symbol
|
||||||
|
return Symbol(string(tk))
|
||||||
|
else
|
||||||
|
return tk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# First, insert keys that match the requested order
|
||||||
|
for target_key in normalized_order
|
||||||
|
if haskey(processed_dict, target_key)
|
||||||
|
out[target_key] = processed_dict[target_key]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Then, append any remaining keys that weren't in the sort_order
|
||||||
|
for (k, v) in processed_dict
|
||||||
|
if !haskey(out, k)
|
||||||
|
out[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# If no sort order is given, just use the processed dict
|
||||||
|
out = processed_dict
|
||||||
|
end
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
# Arrays / vectors: map elements recursively
|
||||||
|
elseif x isa AbstractArray
|
||||||
|
return [dictify(element; keytype=keytype, sort_order=sort_order) for element in x]
|
||||||
|
|
||||||
|
# Everything else: return as-is
|
||||||
|
else
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||||
|
|
||||||
""" Recursively convert dictionary-like variable (e.g. JSON.Object) into a dictionary.
|
""" Recursively convert dictionary-like variable (e.g. JSON.Object) into a dictionary.
|
||||||
@@ -1679,7 +1762,7 @@ function dict_to_string_html(d::AbstractDict; indent_level=1, indent_str=" ")
|
|||||||
padding = indent_str ^ indent_level
|
padding = indent_str ^ indent_level
|
||||||
|
|
||||||
# Sort keys for predictable, clean output
|
# Sort keys for predictable, clean output
|
||||||
for k in sort(collect(keys(d)))
|
for k in keys(d)
|
||||||
v = d[k]
|
v = d[k]
|
||||||
|
|
||||||
if v isa AbstractDict
|
if v isa AbstractDict
|
||||||
@@ -1744,6 +1827,11 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user