quinnj / JSON3.jl

Other
214 stars 47 forks source link

Reading JSON string of specific structure #209

Closed anlumithe closed 2 years ago

anlumithe commented 2 years ago

When generating a type of multiple JSON strings with different structure, reading a JSON string of one specific structure fails with an error invalid JSON. A minimal example:

using JSON3

daily_menu = """{
    "object":"page",
    "date":"23.03.2022"
}"""

dishes = """{
    "object":"list",
    "results":[
        {
            "object":"dish",
            "name":"Spaghetti"
        }
    ]
}"""

JSON3.@generatetypes [daily_menu, dishes]

new_daily_menu = """{
    "object":"page",
    "date":"24.03.2022"
}"""

new_dishes = """{
    "object":"list",
    "results":[
        {
            "object":"dish",
            "name":"Pizza"
        }
    ]
}"""

menu_struct = JSON3.read(new_daily_menu, JSONTypes.Root)

dishes_struct = JSON3.read(new_dishes, JSONTypes.Root)
ERROR: LoadError: ArgumentError: invalid JSON at byte position 38 while parsing type Main.JSONTypes.Result: ExpectedOpeningObjectChar
t":"list",
    "results":[
        {
            "o

Stacktrace:
  [1] invalid(error::JSON3.Error, buf::Base.CodeUnits{UInt8, String}, pos::Int64, T::Type)
    @ JSON3 ~/.julia/packages/JSON3/jf4oo/src/JSON3.jl:29
  [2] #read!#47
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:538 [inlined]
  [3] read!
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:461 [inlined]
  [4] #read#45
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:452 [inlined]
  [5] read
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:451 [inlined]
  [6] macro expansion
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:75 [inlined]
  [7] read(::StructTypes.UnorderedStruct, buf::Base.CodeUnits{UInt8, String}, pos::Int64, len::Int64, b::UInt8, T::Type{Union{Nothing, Main.JSONTypes.Result}}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ JSON3 ~/.julia/packages/JSON3/jf4oo/src/structs.jl:67
  [8] read
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:67 [inlined]
  [9] #_#44
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:445 [inlined]
 [10] MutableClosure
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:444 [inlined]
 [11] applyfield!(f::JSON3.MutableClosure{Base.CodeUnits{UInt8, String}, NamedTuple{(), Tuple{}}}, x::Main.JSONTypes.Root, nm::Symbol)
    @ StructTypes ~/.julia/packages/StructTypes/Cmlkm/src/StructTypes.jl:785
 [12] #read!#47
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:510 [inlined]
 [13] read!
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:461 [inlined]
 [14] #read#45
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:452 [inlined]
 [15] read
    @ ~/.julia/packages/JSON3/jf4oo/src/structs.jl:451 [inlined]
 [16] read(str::String, ::Type{Main.JSONTypes.Root}; jsonlines::Bool, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ JSON3 ~/.julia/packages/JSON3/jf4oo/src/structs.jl:40
 [17] read(str::String, ::Type{Main.JSONTypes.Root})
    @ JSON3 ~/.julia/packages/JSON3/jf4oo/src/structs.jl:33
 [18] top-level scope
    @ ~/Desktop/mlcolab_website/error_example.jl:38

Is there a possibility to generate one type out of two different JSON strings, so that both JSON string structures can be read?

mcmcgrath13 commented 2 years ago

It looks like the generated type is missing that results is a vector. I'll dig into this later.

module JSONTypes

import StructTypes

mutable struct Result
    object::String
    name::String
    Result() = new()
end

mutable struct Root
    object::String
    date::Union{Nothing, String}
    results::Union{Nothing, Result}
    Root() = new()
end

StructTypes.StructType(::Type{Result}) = StructTypes.Mutable()
StructTypes.StructType(::Type{Root}) = StructTypes.Mutable()

end # module