Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to support read json into an OrderedDict? #119

Closed
Moelf opened this issue Jan 31, 2021 · 2 comments
Closed

How to support read json into an OrderedDict? #119

Moelf opened this issue Jan 31, 2021 · 2 comments

Comments

@Moelf
Copy link

Moelf commented Jan 31, 2021

I stabbed myself by using a Dict because I needed to change some values for a configuration file used in another application. Turns out the said application relies on the order of entries in the json file.

How easy it is to support reading into an ordered dictionary (from DataStructures.jl?)

julia> a = tempname()
"/scratch/jl_YMCMDd"

julia> open(a, "w") do f
           write(a, JSON3.write(OrderedDict("a1"=>1, "a2"=>2)))
       end

julia> JSON3.read(read(a, String), Dict) |> JSON3.write
"{\"a2\":2,\"a1\":1}"
julia> JSON3.read(read(a, String)) |> JSON3.write
"{\"a1\":1,\"a2\":2}"
julia> JSON3.read(read(a, String), OrderedDict) |> JSON3.write
ERROR: MethodError: no method matching keytype(::Type{OrderedDict})
@Moelf
Copy link
Author

Moelf commented Jan 31, 2021

wait, I'm dumb this works:

JSON3.read(read(a, String)) |> OrderedDict

@Moelf Moelf closed this as completed Jan 31, 2021
@mkitti
Copy link

mkitti commented Feb 6, 2025

@Moelf 's solution only does the first level and do not recurse through the structure like copy(::JSON3.Object) does for Dict.
To address this, I prototyped the following extension.

baremodule OrderedCollectionsExt

    using OrderedCollections: OrderedDict
    using JSON3: Object, Array
    using Base: Base, copy, map

    function Base.copy(obj::Object, ::Type{OrderedDict})
        dict = OrderedDict{Symbol, Any}()
        for (k, v) in obj
            dict[k] = v isa Object || v isa Array ? copy(v, OrderedDict) : v
        end
        return dict
    end
    Base.copy(arr::Array, ::Type{OrderedDict}) = map(x->x isa Object || x isa Array ? copy(x, OrderedDict) : x, arr)

end

Observe the difference in the returned type of :c:

julia> str = """
       {
           "a": 5,
           "b": 6,
           "c": {
               "d": 7,
               "e": 8
           }
       }
       """
"{\n    \"a\": 5,\n    \"b\": 6,\n    \"c\": {\n        \"d\": 7,\n        \"e\": 8\n    }\n}\n"

julia> OrderedDict(JSON3.read(str))[:c]
Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}} with 2 entries:
  :d => 7
  :e => 8

julia> copy(JSON3.read(str), OrderedDict)[:c]
OrderedDict{Symbol, Any} with 2 entries:
  :d => 7
  :e => 8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants