Skip to content

Advanced Example: The FrankenStruct in the documentation throws an error #410

@hyrodium

Description

@hyrodium

I tried Advanced Example: The FrankenStruct, but it throws the following ArgumentError. Is there any way to resolve the error?

(@v1.12) pkg> activate --temp
  Activating new project at `/tmp/jl_Ab9Wkw`

(jl_Ab9Wkw) pkg> dev JSON
   Resolving package versions...
    Updating `/tmp/jl_Ab9Wkw/Project.toml`
  [682c06a0] + JSON v1.3.0 `~/.julia/dev/JSON`
    Updating `/tmp/jl_Ab9Wkw/Manifest.toml`
  [682c06a0] + JSON v1.3.0 `~/.julia/dev/JSON`
  [69de0a69] + Parsers v2.8.3
  [aea7be01] + PrecompileTools v1.3.3
  [21216c6a] + Preferences v1.5.0
  [ec057cc2] + StructUtils v2.6.0
  [ade2ca70] + Dates v1.11.0
  [56ddb016] + Logging v1.11.0
  [de0858da] + Printf v1.11.0
  [9a3f8284] + Random v1.11.0
  [ea8e919c] + SHA v0.7.0
  [fa267f1f] + TOML v1.0.3
  [cf7118a7] + UUIDs v1.11.0
  [4ec0a83e] + Unicode v1.11.0

(jl_Ab9Wkw) pkg> add StructUtils
   Resolving package versions...
    Updating `/tmp/jl_Ab9Wkw/Project.toml`
  [ec057cc2] + StructUtils v2.6.0
    Manifest No packages added to or removed from `/tmp/jl_Ab9Wkw/Manifest.toml`
Precompiling packages finished.
  5 dependencies successfully precompiled in 14 seconds. 6 already precompiled.

julia> using Dates, JSON, StructUtils

julia> # First, define some types for polymorphic parsing
       abstract type AbstractMonster end

julia> struct Dracula <: AbstractMonster
           num_victims::Int
       end

julia> struct Werewolf <: AbstractMonster
           witching_hour::DateTime
       end

julia> # Define a custom type chooser for AbstractMonster
       JSON.@choosetype AbstractMonster x -> x.monster_type[] == "vampire" ? Dracula : Werewolf

julia> # Define a custom numeric type with special parsing
       struct Percent <: Number
           value::Float64
       end

julia> # Custom lifting for the Percent type
       JSON.lift(::Type{Percent}, x) = Percent(Float64(x))

julia> StructUtils.liftkey(::Type{Percent}, x::String) = Percent(parse(Float64, x))

julia> # Our complex struct with various field types and defaults
       @defaults struct FrankenStruct
           id::Int = 0
           name::String = "Jim"
           address::Union{Nothing, String} = nothing
           rate::Union{Missing, Float64} = missing
           type::Symbol = :a &(json=(name="franken_type",),)
           notsure::Any = nothing
           monster::AbstractMonster = Dracula(0)
           percent::Percent = Percent(0.0)
           birthdate::Date = Date(0) &(json=(dateformat="yyyy/mm/dd",),)
           percentages::Dict{Percent, Int} = Dict{Percent, Int}()
           json_properties::JSONText = JSONText("")
           matrix::Matrix{Float64} = Matrix{Float64}(undef, 0, 0)
       end
fieldtags (generic function with 3 methods)

julia> # A complex JSON input with various features to demonstrate
       json = """
       {
           "id": 1,
           "address": "123 Main St",
           "rate": null,
           "franken_type": "b",
           "notsure": {"key": "value"},
           "monster": {
               "monster_type": "vampire",
               "num_victims": 10
           },
           "percent": 0.1,
           "birthdate": "2023/10/01",
           "percentages": {
               "0.1": 1,
               "0.2": 2
           },
           "json_properties": {"key": "value"},
           "matrix": [[1.0, 2.0], [3.0, 4.0]],
           "extra_key": "extra_value"
       }
       """
"{\n    \"id\": 1,\n    \"address\": \"123 Main St\",\n    \"rate\": null,\n    \"franken_type\": \"b\",\n    \"notsure\": {\"key\": \"value\"},\n    \"monster\": {\n        \"monster_type\": \"vampire\",\n        \"num_victims\": 10\n    },\n    \"percent\": 0.1,\n    \"birthdate\": \"2023/10/01\",\n    \"percentages\": {\n        \"0.1\": 1,\n        \"0.2\": 2\n    },\n    \"json_properties\": {\"key\": \"value\"},\n    \"matrix\": [[1.0, 2.0], [3.0, 4.0]],\n    \"extra_key\": \"extra_value\"\n}\n"

julia> franken = JSON.parse(json, FrankenStruct)
ERROR: ArgumentError: applyeach not applicable for `JSON.LazyValue{String}` with JSON type = `JSONTypes.NUMBER`
Stacktrace:
  [1] applyeach
    @ ~/.julia/dev/JSON/src/lazy.jl:186 [inlined]
  [2] makestruct(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, ::Type{Percent}, source::JSON.LazyValue{String})
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:984
  [3] make(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, T::Type, source::JSON.LazyValue{String})
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:795
  [4] make(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, T::Type, source::JSON.LazyValue{String}, tags::@NamedTuple{})
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:763
  [5] (::StructUtils.var"#findfield##0#findfield##1"{FrankenStruct, JSON.PtrString, JSON.LazyValue{String}, StructUtils.StructClosure{FrankenStruct, Memory{Any}, JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, NTuple{12, Symbol}, NTuple{12, String}}})(i::Int64)
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:948
  [6] macro expansion
    @ ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:607 [inlined]
  [7] _foreach
    @ ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:610 [inlined]
  [8] findfield(::Type{FrankenStruct}, k::JSON.PtrString, v::JSON.LazyValue{String}, f::StructUtils.StructClosure{FrankenStruct, Memory{Any}, JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, NTuple{12, Symbol}, NTuple{12, String}})
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:925
  [9] StructClosure
    @ ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:957 [inlined]
 [10] applyobject(keyvalfunc::StructUtils.StructClosure{FrankenStruct, Memory{Any}, JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, NTuple{12, Symbol}, NTuple{12, String}}, x::JSON.LazyValue{String})
    @ JSON ~/.julia/dev/JSON/src/lazy.jl:284
 [11] applyeach
    @ ~/.julia/dev/JSON/src/lazy.jl:182 [inlined]
 [12] makestruct(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, ::Type{FrankenStruct}, source::JSON.LazyValue{String})
    @ StructUtils ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:984
 [13] make
    @ ~/.julia/packages/StructUtils/BDA5D/src/StructUtils.jl:795 [inlined]
 [14] _parse
    @ ~/.julia/dev/JSON/src/parse.jl:193 [inlined]
 [15] parse(x::JSON.LazyValue{String}, ::Type{FrankenStruct}; dicttype::Type{JSON.Object{String, Any}}, null::Nothing, style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing})
    @ JSON ~/.julia/dev/JSON/src/parse.jl:189
 [16] parse
    @ ~/.julia/dev/JSON/src/parse.jl:189 [inlined]
 [17] parse(buf::String, ::Type{FrankenStruct})
    @ JSON ~/.julia/dev/JSON/src/parse.jl:181
 [18] top-level scope
    @ REPL[14]:1

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