@@ -37,7 +37,7 @@ mutable struct StreamingParserState{T <: IO} <: ParserState
3737end
3838StreamingParserState (io:: IO ) = StreamingParserState (io, 0x00 , true , PushVector {UInt8} ())
3939
40- struct ParserContext{DictType, IntType, AllowNanInf} end
40+ struct ParserContext{DictType, IntType, AllowNanInf, NullValue } end
4141
4242"""
4343Return the byte at the current position of the `ParserState`. If there is no
@@ -173,7 +173,8 @@ function parse_value(pc::ParserContext, ps::ParserState)
173173 end
174174end
175175
176- function parse_jsconstant (:: ParserContext{<:Any,<:Any,AllowNanInf} , ps:: ParserState ) where AllowNanInf
176+ function parse_jsconstant (:: ParserContext{<:Any,<:Any,AllowNanInf,NullValue} ,
177+ ps:: ParserState ) where {AllowNanInf,NullValue}
177178 c = advance! (ps)
178179 if c == LATIN_T # true
179180 skip! (ps, LATIN_R, LATIN_U, LATIN_E)
@@ -183,7 +184,7 @@ function parse_jsconstant(::ParserContext{<:Any,<:Any,AllowNanInf}, ps::ParserSt
183184 false
184185 elseif c == LATIN_N # null
185186 skip! (ps, LATIN_U, LATIN_L, LATIN_L)
186- nothing
187+ NullValue
187188 elseif AllowNanInf && c == LATIN_UPPER_N
188189 skip! (ps, LATIN_A, LATIN_UPPER_N)
189190 NaN
@@ -427,20 +428,21 @@ function unparameterize_type(T::Type)
427428end
428429
429430# Workaround for slow dynamic dispatch for creating objects
430- const DEFAULT_PARSERCONTEXT = ParserContext {Dict{String, Any}, Int64, false} ()
431- function _get_parsercontext (dicttype, inttype, allownan)
431+ const DEFAULT_PARSERCONTEXT = ParserContext {Dict{String, Any}, Int64, false, nothing } ()
432+ function _get_parsercontext (dicttype, inttype, allownan, null )
432433 if dicttype == Dict{String, Any} && inttype == Int64 && ! allownan
433434 DEFAULT_PARSERCONTEXT
434435 else
435- ParserContext{unparameterize_type (dicttype), inttype, allownan}. instance
436+ ParserContext{unparameterize_type (dicttype), inttype, allownan, null }. instance
436437 end
437438end
438439
439440"""
440441 parse{T<:Associative}(str::AbstractString;
441442 dicttype::Type{T}=Dict,
442443 inttype::Type{<:Real}=Int64,
443- allownan::Bool=true)
444+ allownan::Bool=true,
445+ null=nothing)
444446
445447Parses the given JSON string into corresponding Julia types.
446448
@@ -449,12 +451,14 @@ Keyword arguments:
449451 • inttype: Real number type to use when parsing JSON numbers that can be parsed
450452 as integers (default: Int64)
451453 • allownan: allow parsing of NaN, Infinity, and -Infinity (default: true)
454+ • null: value to use for parsed JSON `null` values (default: `nothing`)
452455"""
453456function parse (str:: AbstractString ;
454457 dicttype= Dict{String,Any},
455458 inttype:: Type{<:Real} = Int64,
456- allownan:: Bool = true )
457- pc = _get_parsercontext (dicttype, inttype, allownan)
459+ allownan:: Bool = true ,
460+ null= nothing )
461+ pc = _get_parsercontext (dicttype, inttype, allownan, null)
458462 ps = MemoryParserState (str, 1 )
459463 v = parse_value (pc, ps)
460464 chomp_space! (ps)
468472 parse{T<:Associative}(io::IO;
469473 dicttype::Type{T}=Dict,
470474 inttype::Type{<:Real}=Int64,
471- allownan=true)
475+ allownan=true,
476+ null=nothing)
472477
473478Parses JSON from the given IO stream into corresponding Julia types.
474479
@@ -477,12 +482,14 @@ Keyword arguments:
477482 • inttype: Real number type to use when parsing JSON numbers that can be parsed
478483 as integers (default: Int64)
479484 • allownan: allow parsing of NaN, Infinity, and -Infinity (default: true)
485+ • null: value to use for parsed JSON `null` values (default: `nothing`)
480486"""
481487function parse (io:: IO ;
482488 dicttype= Dict{String,Any},
483489 inttype:: Type{<:Real} = Int64,
484- allownan:: Bool = true )
485- pc = _get_parsercontext (dicttype, inttype, allownan)
490+ allownan:: Bool = true ,
491+ null= nothing )
492+ pc = _get_parsercontext (dicttype, inttype, allownan, null)
486493 ps = StreamingParserState (io)
487494 parse_value (pc, ps)
488495end
492499 dicttype=Dict{String, Any},
493500 inttype::Type{<:Real}=Int64,
494501 allownan::Bool=true,
502+ null=nothing,
495503 use_mmap::Bool=true)
496504
497505Convenience function to parse JSON from the given file into corresponding Julia types.
@@ -501,17 +509,19 @@ Keyword arguments:
501509 • inttype: Real number type to use when parsing JSON numbers that can be parsed
502510 as integers (default: Int64)
503511 • allownan: allow parsing of NaN, Infinity, and -Infinity (default: true)
512+ • null: value to use for parsed JSON `null` values (default: `nothing`)
504513 • use_mmap: use mmap when opening the file (default: true)
505514"""
506515function parsefile (filename:: AbstractString ;
507516 dicttype= Dict{String, Any},
508517 inttype:: Type{<:Real} = Int64,
518+ null= nothing ,
509519 allownan:: Bool = true ,
510520 use_mmap:: Bool = true )
511521 sz = filesize (filename)
512522 open (filename) do io
513523 s = use_mmap ? String (Mmap. mmap (io, Vector{UInt8}, sz)) : read (io, String)
514- parse (s; dicttype= dicttype, inttype= inttype, allownan= allownan)
524+ parse (s; dicttype= dicttype, inttype= inttype, allownan= allownan, null = null )
515525 end
516526end
517527
0 commit comments