Why does Julia not support JSON syntax to create a Dict?

Macros can only operate on syntactically valid Julia code, since they always operate on expression objects. Single quotes (') in Julia always denote single-character literals, so something like 'abc' is not valid syntax, so this will error during parsing. Disallowing multi-character strings enclosed with single quotes was a conscious decision, because otherwise you would get parsing ambiguities, since ' is also a postfix operator for adjoint. For this specific case, a non-standard string literal would probably make more sense.

5 Likes

Thanks for the explanation. Did I understood you correctly that:

@js { d: 'thirty', 123 } 

is not possible, but

js"{ d: 'thirty', 123 }" 

could be?

4 Likes

Yes! It should be as simple as:

using JSON3
macro js_str(s)
    return :(JSON3.read($s))
end
4 Likes

Thanks. Pretty cool! However, the same problem persists:

julia> using JSON3

julia> macro js_str(s)
           return :(JSON3.read($s))
       end
@js_str (macro with 1 method)

julia> js"{\"a_number\" : 5.0, \"an_array\" : [\"string\", 9]}"
Dict{String,Any} with 2 entries:
  "an_array" => Any["string", 9]
  "a_number" => 5.0

julia> js"{'a_number' : 5.0, 'an_array' : ['string', 9]}"
ERROR: Invalid object key
Line: 0
Around: ...{'a_number' : 5.0, 'an...
            ^

Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] _error(::String, ::JSON.Parser.MemoryParserState) at C:\Users\tfr004\.julia\packages\JSON\d89fA\src\Parser.jl:142
 [3] parse_object(::JSON.Parser.ParserContext{Dict{String,Any},Int64,true,nothing}, ::JSON.Parser.MemoryParserState) at C:\Users\tfr004\.julia\packages\JSON\d89fA\src\Parser.jl:227
 [4] parse_value(::JSON.Parser.ParserContext{Dict{String,Any},Int64,true,nothing}, ::JSON.Parser.MemoryParserState) at C:\Users\tfr004\.julia\packages\JSON\d89fA\src\Parser.jl:168
 [5] #parse#1(::Type, ::Type{Int64}, ::Bool, ::Nothing, ::typeof(JSON.Parser.parse), ::String) at C:\Users\tfr004\.julia\packages\JSON\d89fA\src\Parser.jl:463
 [6] parse(::String) at C:\Users\tfr004\.julia\packages\JSON\d89fA\src\Parser.jl:461
 [7] top-level scope at REPL[16]:1

julia>

Possibly because 'key' is not valid JSON syntax. You need "key". And then probably you want """ to make your life easier, eg

julia> js"""{"a_number" : 5.0, "an_array" : ["string", 9]}"""
JSON3.Object{Base.CodeUnits{UInt8,String},Array{UInt64,1}} with 2 entries:
  :a_number => 5
  :an_array => Any["string", 9]
2 Likes

Have a look at Simon’s JSServe.jl

It might be of some interest :slight_smile:

Try this

julia> js"""
       {
           "a_number" : 5.0,
           "an_array" : ["string", 9]
       }
       """
JSON3.Object{Base.CodeUnits{UInt8,String},Array{UInt64,1}} with 2 entries:
  :a_number => 5
  :an_array => Any["string", 9]

:slight_smile:

Edit: If you really wanted a Dict, just do this

julia> macro js_str(s)
           return :(Dict(JSON3.read($s)))
       end
@js_str (macro with 1 method)

julia> js"""
       {
           "a_number" : 5.0,
           "an_array" : ["string", 9]
       }
       """
Dict{Symbol,Any} with 2 entries:
  :a_number => 5
  :an_array => Any["string", 9]

:nerd_face:

2 Likes