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

Reading and writing is broken for Dicts with struct keys #71

Open
DilumAluthge opened this issue Aug 16, 2020 · 2 comments
Open

Reading and writing is broken for Dicts with struct keys #71

DilumAluthge opened this issue Aug 16, 2020 · 2 comments

Comments

@DilumAluthge
Copy link
Contributor

See the MWE below. I would have expected that when I read the object back in, the keys would have been Foo("a") and Foo("c"). Instead, they are Foo("Foo(\"a\")") and Foo("Foo(\"c\")"), which is not correct.

MWE:

julia> import JSON3

julia> import StructTypes

julia> mutable struct Foo
           value::String
           Foo() = new()
           Foo(value) = new(value)
       end

julia> mutable struct Bar
           value::String
           Bar() = new()
           Bar(value) = new(value)
       end

julia> mutable struct Baz
           dict::Dict{Foo, Bar}
           Baz() = new()
           Baz(dict) = new(dict)
       end

julia> StructTypes.StructType(::Type{Foo}) = StructTypes.Mutable()

julia> StructTypes.StructType(::Type{Bar}) = StructTypes.Mutable()

julia> StructTypes.StructType(::Type{Baz}) = StructTypes.Mutable()

julia> a = Baz(Dict{Foo, Bar}(Foo("a") => Bar("b"), Foo("c") => Bar("d")))
Baz(Dict{Foo,Bar}(Foo("a") => Bar("b"),Foo("c") => Bar("d")))

julia> keys(a.dict)
KeySet for a Dict{Foo,Bar} with 2 entries. Keys:
  Foo("a")
  Foo("c")

julia> values(a.dict)
ValueIterator for a Dict{Foo,Bar} with 2 entries. Values:
  Bar("b")
  Bar("d")

julia> b = JSON3.write(a)
"{\"dict\":{\"Foo(\\\"a\\\")\":{\"value\":\"b\"},\"Foo(\\\"c\\\")\":{\"value\":\"d\"}}}"

julia> c = JSON3.read(b, Baz)
Baz(Dict{Foo,Bar}(Foo("Foo(\"c\")") => Bar("d"),Foo("Foo(\"a\")") => Bar("b")))

julia> keys(c.dict)
KeySet for a Dict{Foo,Bar} with 2 entries. Keys:
  Foo("Foo(\"c\")")
  Foo("Foo(\"a\")")

julia> values(c.dict)
ValueIterator for a Dict{Foo,Bar} with 2 entries. Values:
  Bar("d")
  Bar("b")

cc: @quinnj

@quinnj
Copy link
Owner

quinnj commented Aug 18, 2020

Yeah, this is related to #34; the problem is that JSON requires keys to be strings, so we always write/parse keys as strings. Your example might be more complex, but perhaps you want Foo to actually be StructTypes.StringType? That is currently supported and works fine (writing/reading), but yeah, still need to think more broadly about whether we can find a way to support non-StructTypes.StringType types as keys in DictType writing/reading.

@DilumAluthge
Copy link
Contributor Author

Hmm. This might be tricky. In a different example, I will have a Dict where the keys are of type Foo where Foo might be something like this:

struct Foo
    a::String
    b::Int
    c::SomeOtherType

So it will be tricky to get Foo to be of type StructTypes.StringType.

One workaround I've found is to convert the Dict to a vector of key-value pairs before writing. Then when you read it back in, you convert the vector of pairs back to a Dict. It's not very elegant though.

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