JSON parsing gives error message with Dash

This code runs fine and JSON.parse() works as expected.

using Dash
using DataFrames
using CSV
using Base64
using JSON

# example data
data_dict = Dict("group" => ["A", "A", "B", "B"],
                 "height" => [1, 2, 3, 4])

# convert into dataframe
data = DataFrame(data_dict)

# convert dataframe to JSON
json_data = JSON.json(data)

# convert JSON back to dataframe
dataframe_data = DataFrame(JSON.parse(json_data))

# save data to read in from Dash app
CSV.write("example.csv", data)

But when I use this in a Dash app, I get an error message, although subsequent code seems to work, suggesting it’s not an error.

app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"],
           suppress_callback_exceptions=true)

app.layout = html_div() do
    html_h2("Title"),
    html_br(), 
    dcc_upload(id="file",
               children=html_div(html_a("Drag and drop or select file")),
               style=Dict("width" => "40%",
                          "height" => "60px",
                          "lineHeight" => "60px",
                          "borderWidth" => "1px",
                          "borderStyle" => "dashed",
                          "borderRadius" => "5px",
                          "textAlign" => "center",
                          "margin" => "10px")),
    html_br(),
    dcc_store(id="store_data", data=[], storage_type="session"),     
    html_div(id="select_targets") 
end

# read in data from file and return data in JSON format
callback!(app,
          Output("store_data", "data"),
          Input("file", "contents")
          ) do contents
              if (contents isa Nothing)
                  return no_update
              else
                  content_type, content_string = split(contents, ',')
                  decoded = base64decode(content_string)
                  str = String(decoded)
                  df = CSV.read(IOBuffer(str), DataFrame)
                  return JSON.json(df)
              end          
          end

# select factor level from column
callback!(app,
          Output("select_targets", "children"), 
          Input("store_data", "data"),
          prevent_initial_call=true) do stored_json_data

              # get info on stored data
              # println(stored_json_data) # --> returns NamedTuple()
              # println(typeof(stored_json_data)) # --> returns NamedTuple{(), Tuple{}}
              
              # convert from JSON to dataframe
              d = DataFrame(JSON.parse(stored_json_data)) # error is here
              
              return html_div([
                  html_br(), 
                  html_p("Select target"),
                  dcc_dropdown(id="target",
                               options=[(label = i, value=i) for i in unique(d.group)],
                               style=Dict("width" => "40%")), # this line works and creates dropdown
                  html_button("Create graph", id="button")
              ])
          end


run_server(app, "0.0.0.0", debug=true)

Error message is below and it seems that JSON data gets converted to a named tuple.

MethodError: no method matching parse(::NamedTuple{(), Tuple{}})
Closest candidates are:
  parse(!Matched::AbstractString; dicttype, inttype, allownan, null) at /home/sel/.julia/packages/JSON/QXB8U/src/Parser.jl:443
  parse(!Matched::IO; dicttype, inttype, allownan, null) at /home/sel/.julia/packages/JSON/QXB8U/src/Parser.jl:474
  parse(!Matched::Type{Plot}, !Matched::AbstractString) at /home/sel/.julia/packages/PlotlyBase/xb3Du/src/json.jl:68

Stacktrace:
 [1] (::var"#45#47")(stored_json_data::NamedTuple{(), Tuple{}})
   @ Main ./REPL[44]:12

Am I missing something? Julia version is below and all packages updated today.

Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)

I figured it out. The error occurs because before uploading a file, stored_json_data is empty, and hence an empty tuple is returned, which cannot be parsed. The solution is to test if isempty(stored_json_data), and if true I just return a line break.

callback!(app,
          Output("select_targets", "children"), 
          Input("store_data", "data"),
          prevent_initial_call=true) do stored_json_data

              if isempty(stored_json_data)
                  return html_br()
              else 
                  
                  # convert from JSON to dataframe
                  d = DataFrame(JSON.parse(stored_json_data)) # error is here
                  
                  return html_div([
                      html_br(), 
                      html_p("Select target"),
                      dcc_dropdown(id="target",
                                   options=[(label = i, value=i) for i in unique(d.group)],
                                   style=Dict("width" => "40%")),
                      html_button("Create graph", id="button")
                  ])
              end
          end