# Deserealize from/to JSON

**URL:** <https://discourse.julialang.org/t/deserealize-from-to-json/33486>\
**Category:** General Usage\
**Created:** [January 17, 2020, 12:07pm UTC](https://discourse.julialang.org/t/deserealize-from-to-json/33486 "2020-01-17T12:07:04Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [January 17, 2020, 12:07pm UTC](https://discourse.julialang.org/t/deserealize-from-to-json/33486/1 "2020-01-17T12:07:04Z")

</div>

I would like to have a quick and dirty way to load/save custom julia structs to a human readable format, say JSON.

### Goals

- Human readable
- Works out of the box for user defined structs
- Should be simple to implement
- Should not require passing type information

### Non Goals

- Performance
- Security

Here is what I tried so far:

```julia
module H
using ArgCheck
using ConstructionBase: constructorof

KEY_META = " __meta__"
KEY_CONSTRUCTOR = "constructor"
KEY_PROPERTYNAMES = "propertynames"

function marshal_struct(o)
    d = Dict{String, Any}()
    meta = Dict(
        KEY_CONSTRUCTOR => string(constructorof(typeof(o))),
        KEY_PROPERTYNAMES => collect(map(string, propertynames(o))),
    )
    d[KEY_META] = meta
    for prop in propertynames(o)
        key = string(prop)
        d[key] = marshal(getproperty(o, prop))
    end
    d
end

marshal(o) = marshal_struct(o)
marshal(o::String) = o
marshal(o::Number) = o

unmarshal(o::String, ctx) = o
unmarshal(o::Number, ctx) = o

function unmarshal(d::Dict, eval)
    @argcheck haskey(d, KEY_META)
    meta = d[KEY_META]
    @check haskey(meta, KEY_CONSTRUCTOR)
    @check haskey(meta, KEY_PROPERTYNAMES)
    
    ctor_str = meta[KEY_CONSTRUCTOR]
    @check ctor_str isa String
    ctor_expr = nothing
    try
        ctor_expr = Meta.parse(ctor_str)
    catch err
        msg = """Error parsing constructor:
        string: $ctor_str
        error: $err
        """
        error(msg)
    end
    ctor = nothing
    try
        ctor = eval(ctor_expr)
    catch err
        msg = """Error evaluating constructor expression:
        string: $ctor_str
        expr: $ctor_expr
        error: $err
        """
        error(msg)
    end
    propnames = meta[KEY_PROPERTYNAMES]
    args = map(propnames) do key
        unmarshal(d[key], eval)
    end
    ctor(args...)
end
end#module

struct S{A,B}
    a::A
    b::B
end

s = S(1, 2.0)
d = H.marshal(s)
s2 = H.unmarshal(d, eval)
@show s
@show d
@show s2

```

```julia-auto
s = S{Int64,Float64}(1, 2.0)
d = Dict{String,Any}("b" => 2.0," __meta__" => Dict{String,Any}("propertynames" => ["a", "b"],"constructor" => "S"),"a" => 1)
s2 = S{Int64,Float64}(1, 2.0)

```

In order to load user defined structs, one needs to call `eval` at some point. My problem is, that this `eval` must be the `eval` of the calling module, not the `eval` of the module that defines the marshaling functionality. That is why the user needs to pass his `eval`…

How to avoid passing the user module `eval`?  
`JLD.jl` must have solved this problem, but I cannot understand the code.  
Or is there another approach?

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [January 17, 2020, 1:14pm UTC](https://discourse.julialang.org/t/deserealize-from-to-json/33486/2 "2020-01-17T13:14:36Z")

</div>

It seems that `JLD.jl` uses `Core.eval(Main, expr)` for evaluating the type.
