Skip to content

Commit 55ee550

Browse files
authored
Merge pull request #143 from plotly/json3
Replacing JSON2 package with JSON3
2 parents 4190e5d + faaf0ae commit 55ee550

19 files changed

+133
-66
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DashTable = "1b08a953-4be3-4667-9a23-f0e2ba4deb9a"
1212
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1313
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
1414
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
15-
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
15+
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
1616
MD5 = "6ac74813-4b46-53a4-afec-0b5dc9d7885c"
1717
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1818
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
@@ -30,7 +30,7 @@ DashTable = "5.0.0"
3030
DataStructures = "0.17, 0.18"
3131
HTTP = "0.8.10, 0.9"
3232
JSON = "0.21"
33-
JSON2 = "0.3"
33+
JSON3 = "1.9"
3434
MD5 = "0.2"
3535
PlotlyBase = "0.8.5, 0.8.6"
3636
YAML = "0.4.7"

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,5 @@ Be careful - in Dash.jl states come first in an arguments list.
189189

190190
### JSON:
191191

192-
I use JSON2.jl for JSON serialization/deserialization, so in callbacks all JSON objects are `NamedTuples` rather than dictionaries. Within component properties you can use both `Dict` and `NamedTuple` for JSON objects.
193-
192+
I use JSON3.jl for JSON serialization/deserialization.
194193
Note when declaring elements with a single properly that `layout = (title = "Test graph")` is not interpreted as a `NamedTuple` by Julia - you'll need to add a comma when declaring the layout, e.g. `layout = (title = "Test graph",)`

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,4 @@ Be careful - in Dashboards states came first in arguments list
174174

175175
### json:
176176

177-
I use JSON2 for json serialization/deserialization, so in callbacks all json objects are NamedTuples not Dicts. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: `layout = (title = "Test graph")` is not interpreted as NamedTuple by Julia - you need add comma at the end `layout = (title = "Test graph",)`
177+
I use JSON3 for json serialization/deserialization. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: `layout = (title = "Test graph")` is not interpreted as NamedTuple by Julia - you need add comma at the end `layout = (title = "Test graph",)`

src/Dash.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
module Dash
22
using DashBase
3-
import HTTP, JSON2, CodecZlib, MD5
3+
import HTTP, JSON3, CodecZlib, MD5
44
using Sockets
55
using Pkg.Artifacts
6+
67
const ROOT_PATH = realpath(joinpath(@__DIR__, ".."))
78
#const RESOURCE_PATH = realpath(joinpath(ROOT_PATH, "resources"))
89
include("exceptions.jl")
@@ -25,6 +26,7 @@ include("resources/application.jl")
2526
include("handlers.jl")
2627
include("server.jl")
2728
include("init.jl")
29+
include("plotly_base.jl")
2830

2931
@doc """
3032
module Dash
@@ -107,6 +109,8 @@ function __init__()
107109
end
108110

109111

112+
JSON3.StructTypes.StructType(::Type{DashBase.Component}) = JSON3.StructTypes.Struct()
113+
JSON3.StructTypes.excludes(::Type{DashBase.Component}) = (:name, :available_props, :wildcard_regex)
110114

111115

112-
end # module
116+
end # module

src/app/supporttypes.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ struct Wildcard
22
type ::Symbol
33
end
44

5-
JSON2.write(io::IO, wild::Wildcard; kwargs...) = Base.write(io, "[\"", wild.type, "\"]")
5+
JSON3.StructTypes.StructType(::Type{Wildcard}) = JSON3.RawType()
6+
7+
JSON3.rawbytes(wild::Wildcard) = string("[\"", wild.type, "\"]")
68

79
const MATCH = Wildcard(:MATCH)
810
const ALL = Wildcard(:ALL)
@@ -30,6 +32,8 @@ const Input = Dependency{TraitInput}
3032
const State = Dependency{TraitState}
3133
const Output = Dependency{TraitOutput}
3234

35+
JSON3.StructTypes.StructType(::Type{<:Dependency}) = JSON3.StructTypes.Struct()
36+
3337
"""
3438
Base.==(a::Dependency, b::Dependency)
3539
@@ -97,6 +101,9 @@ struct ClientsideFunction
97101
namespace ::String
98102
function_name ::String
99103
end
104+
105+
JSON3.StructTypes.StructType(::Type{ClientsideFunction}) = JSON3.StructTypes.Struct()
106+
100107
struct Callback
101108
func ::Union{Function, ClientsideFunction}
102109
dependencies ::CallbackDeps

src/handler/callback_context.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ function callback_context()
3535
return get_context(_callback_context_storage)
3636
end
3737

38-
function inputs_list_to_dict(list::Vector{Any})
38+
function inputs_list_to_dict(list::AbstractVector)
3939
result = Dict{String, Any}()
4040
_item_to_dict!.(Ref(result), list)
4141
return result
4242
end
4343

44-
dep_id_string(id::NamedTuple) = sorted_json(id)
44+
dep_id_string(id::AbstractDict) = sorted_json(id)
4545
dep_id_string(id::AbstractString) = String(id)
4646
function _item_to_dict!(target::Dict{String, Any}, item)
4747
target["$(dep_id_string(item.id)).$(item.property)"] = get(item, :value, nothing)
4848
end
4949

50-
_item_to_dict!(target::Dict{String, Any}, item::Vector) = _item_to_dict!.(Ref(target), item)
50+
_item_to_dict!(target::Dict{String, Any}, item::AbstractVector) = _item_to_dict!.(Ref(target), item)

src/handler/index_page.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function config_html(app::DashApp)
9393
max_retry = get_devsetting(app, :hot_reload_max_retry)
9494
)
9595
end
96-
return """<script id="_dash-config" type="application/json">$(JSON2.write(config))</script>"""
96+
return """<script id="_dash-config" type="application/json">$(JSON3.write(config))</script>"""
9797
end
9898

9999

src/handler/processors/callback.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ function split_callback_id(callback_id::AbstractString)
1212
end
1313

1414
input_to_arg(input) = get(input, :value, nothing)
15-
input_to_arg(input::Vector) = input_to_arg.(input)
15+
input_to_arg(input::AbstractVector) = input_to_arg.(input)
1616

1717
make_args(inputs, state) = vcat(input_to_arg(inputs), input_to_arg(state))
1818

1919
res_to_vector(res) = res
2020
res_to_vector(res::Vector) = res
2121

22-
function _push_to_res!(res, value, out::Vector)
22+
function _push_to_res!(res, value, out::AbstractVector)
2323
_push_to_res!.(Ref(res), value, out)
2424
end
2525
function _push_to_res!(res, value, out)
@@ -47,6 +47,7 @@ function process_callback_call(app, callback_id, outputs, inputs, state)
4747

4848
_push_to_res!(response, res_vector, outputs)
4949

50+
5051
if length(response) == 0
5152
throw(PreventUpdate())
5253
end
@@ -59,7 +60,7 @@ function process_callback(request::HTTP.Request, state::HandlerState)
5960
app = state.app
6061
response = HTTP.Response(200, ["Content-Type" => "application/json"])
6162

62-
params = JSON2.read(String(request.body))
63+
params = JSON3.read(String(request.body))
6364
inputs = get(params, :inputs, [])
6465
state = get(params, :state, [])
6566
output = Symbol(params[:output])
@@ -74,7 +75,7 @@ function process_callback(request::HTTP.Request, state::HandlerState)
7475
cb_result = with_callback_context(context) do
7576
process_callback_call(app, output, outputs_list, inputs, state)
7677
end
77-
response.body = Vector{UInt8}(JSON2.write(cb_result))
78+
response.body = Vector{UInt8}(JSON3.write(cb_result))
7879
catch e
7980
if isa(e,PreventUpdate)
8081
return HTTP.Response(204)

src/handler/processors/layout.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ function process_layout(request::HTTP.Request, state::HandlerState)
44
return HTTP.Response(
55
200,
66
["Content-Type" => "application/json"],
7-
body = JSON2.write(layout_data(state.app.layout))
7+
body = JSON3.write(layout_data(state.app.layout))
88
)
99
end

src/handler/processors/reload_hash.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ function process_reload_hash(request::HTTP.Request, state::HandlerState)
44
hard = state.reload.hard,
55
packages = keys(state.cache.resources.files),
66
files = state.reload.changed_assets
7-
)
7+
)
88
state.reload.hard = false
99
state.reload.changed_assets = []
10-
return HTTP.Response(200, ["Content-Type" => "application/json"], body = JSON2.write(reload_tuple))
10+
return HTTP.Response(200, ["Content-Type" => "application/json"], body = JSON3.write(reload_tuple))
1111

1212
end

src/handler/state.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function _dependencies_json(app::DashApp)
3131
prevent_initial_call = callback.prevent_initial_call
3232
)
3333
end
34-
return JSON2.write(result)
34+
return JSON3.write(result)
3535
end
3636

3737
function _cache_tuple(app::DashApp, registry::ResourcesRegistry)

src/plotly_base.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import PlotlyBase
2+
import JSON
3+
4+
function DashBase.to_dash(p::PlotlyBase.Plot)
5+
data = JSON.lower(p)
6+
pop!(data, :config, nothing)
7+
return data
8+
end

src/utils/misc.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function format_tag(name ::String, attributes::Dict{String, String}, inner::Stri
1010
tag *= "/>"
1111
elseif opened
1212
tag *= ">"
13-
else
13+
else
1414
tag *= ">$inner</$name>"
1515
end
1616
end
@@ -32,7 +32,7 @@ function validate_index(name::AbstractString, index::AbstractString, checks::Vec
3232
string(
3333
"Missing item", (length(missings)>1 ? "s" : ""), " ",
3434
join(getindex.(missings, 1), ", "),
35-
" in ", name
35+
" in ", name
3636
)
3737
)
3838
end
@@ -43,26 +43,26 @@ macro var_str(s)
4343
end
4444

4545
function parse_props(s)
46-
function make_prop(part)
46+
function make_prop(part)
4747
m = match(r"^(?<id>[A-Za-z]+[\w\-\:\.]*)\.(?<prop>[A-Za-z]+[\w\-\:\.]*)$", strip(part))
4848
if isnothing(m)
4949
error("expected <id>.<property>[,<id>.<property>...] in $(part)")
5050
end
51-
51+
5252
return (Symbol(m[:id]), Symbol(m[:prop]))
53-
end
53+
end
5454

5555
props_parts = split(s, ",", keepempty = false)
56-
56+
5757
return map(props_parts) do part
5858
return make_prop(part)
59-
end
59+
end
6060
end
6161

6262
function generate_hash()
63-
return strip(string(UUIDs.uuid4()), '-')
63+
return strip(string(UUIDs.uuid4()), '-')
6464
end
6565

66-
sort_by_keys(data::NamedTuple) = (;sort!(collect(pairs(data)), by = (x)->x[1])...,)
66+
sort_by_keys(data) = (;sort!(collect(pairs(data)), by = (x)->x[1])...,)
6767

68-
sorted_json(data::NamedTuple) = JSON2.write(sort_by_keys(data))
68+
sorted_json(data) = JSON3.write(sort_by_keys(data))

0 commit comments

Comments
 (0)