quinnj / JSON3.jl

Other
214 stars 47 forks source link

Generate code from an array of JSON samples #142

Open kskyten opened 3 years ago

kskyten commented 3 years ago

Currently, JSON3.generatetypes only accepts a JSON string as an argument. It would be useful to accept a list of JSON samples from an API for example. I tried to look into this a bit, but couldn't get it working yet. It seems like generate_type(a::JSON3.Array) would work on vectors of JSON3.Objects by just changing the signature. Then a corresponding generatetypes(json_strs::Vector{<:AbstractString}, ...) method could be implemented using it.

mcmcgrath13 commented 3 years ago

The raw types would need to be unified before generating the expressions, but that could also be achieved with a map/reduce approach.

maybe something like:

read_json_str(json_str) = read(length(json_str) < 255 && isfile(json_str) ? Base.read(json_str, String) : json_str)

function generatetypes(
    json_str::Vector{AbstractString},
    module_name::Symbol;
    mutable::Bool = true,
    root_name::Symbol = :Root,
)
    # either a JSON.Array or JSON.Object
    json = read_json_str.(json_str)

    # build a type for the JSON
    raw_json_type = reduce(unify, generate_type.(json); init=Top)
    json_exprs = generate_exprs(raw_json_type; root_name=root_name)
    return generate_struct_type_module(
        json_exprs,
        module_name
    )
end

Not sure if this is the best approach, but I'm a bit hesitant to change/add to the type signatures in generate_type as that is really intended for parsed JSON(3) at that point.

quinnj commented 3 years ago

I like the proposal by @mcmcgrath13 here of having an additional method that takes Vector{<:AbstractString} and does a map-reduce on the types.