Skip to content

Multiple Styles for same Struct not working #434

@BenCurran98

Description

@BenCurran98

Hi! Firstly, thanks for the recent upgrade to 1.0 - very cool!

I've encountered some issues with trying to use multiple different styles to parse the same underlying struct in different ways (use case would be e.g. trying to encode a point in some "custom" way vs encoding it in geojson format).

If I build on the DateTime example in the docs, I get the following MWE:

struct DateTimeStyle <: JSON.JSONStyle end
struct OtherDateStyle <: JSON.JSONStyle end

# Define how to serialize Date and DateTime in this style
JSON.lower(::DateTimeStyle, d::Date) = string(d)
JSON.lift(::DateTimeStyle, ::Type{Date}, x::Union{JSON.LazyArray{T}, JSON.LazyObject{T}, JSON.LazyValue{T}}) where T = DateTime(x[])

# Define a slightly different encoding
JSON.lower(::OtherDateStyle, dt::Date) = (; time = string(dt))
StructUtils.lift(::OtherDateStyle, ::Type{Date}, x::Union{JSON.LazyArray{T}, JSON.LazyObject{T}, JSON.LazyValue{T}}) where T = DateTime(x[].time)

# neither of these work
JSON.parse(JSON.json(Date(2023, 1, 1); style=DateTimeStyle()), Date, style = DateTimeStyle())
JSON.parse(JSON.json(Date(2023, 1, 1); style=OtherDateStyle()), Date, style = OtherDateStyle())

The error I get is:

ERROR: MethodError: no method matching iterate(::DateTime)
The function `iterate` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  iterate(::DataStructures.IntSet)
   @ DataStructures ~/.julia/packages/DataStructures/qUuAY/src/int_set.jl:171
  iterate(::DataStructures.IntSet, ::Int64)
   @ DataStructures ~/.julia/packages/DataStructures/qUuAY/src/int_set.jl:173
  iterate(::DataStructures.IntSet, ::Int64, ::Any)
   @ DataStructures ~/.julia/packages/DataStructures/qUuAY/src/int_set.jl:173
  ...

Stacktrace:
 [1] indexed_iterate(I::DateTime, i::Int64)
   @ Base ./tuple.jl:165
 [2] _parse
   @ ~/.julia/dev/JSON/src/parse.jl:193 [inlined]
 [3] parse(x::JSON.LazyValue{String}, ::Type{Date}; dicttype::Type{JSON.Object{String, Any}}, null::Nothing, style::DateTimeStyle)
   @ JSON ~/.julia/dev/JSON/src/parse.jl:189
 [4] parse
   @ ~/.julia/dev/JSON/src/parse.jl:189 [inlined]
 [5] #parse#52
   @ ~/.julia/dev/JSON/src/parse.jl:181 [inlined]
 [6] top-level scope
   @ REPL[32]:1

Not sure if I'm doing something wrong here? I suspect it has something to do with the return value of StructUtils.lift, as in the code it looks like it uses the output of defaultstate(st) to check the buffer position here

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions