diff --git a/src/lazy.jl b/src/lazy.jl index e122699..cf08cc6 100644 --- a/src/lazy.jl +++ b/src/lazy.jl @@ -587,8 +587,23 @@ isbigfloat(x::NumberResult) = x.tag == BIGFLOAT b = getbyte(buf, pos) startpos = pos isneg = isfloat = overflow = false - if !opts.allownan + if opts.allownan + # If this doesn't start like an integer, let Parsers handle + # NaN/Inf/-Inf and the configured special values. + if b == UInt8('-') || b == UInt8('+') + if pos == len + error = UnexpectedEOF + @goto invalid + end + b = getbyte(buf, pos + 1) + isfloat = !(UInt8('0') <= b <= UInt8('9')) + else + isfloat = !(UInt8('0') <= b <= UInt8('9')) + end + end + if !isfloat val = Int64(0) + b = getbyte(buf, pos) isneg = b == UInt8('-') if isneg || b == UInt8('+') # spec doesn't allow leading +, but we do pos += 1 @@ -652,7 +667,8 @@ isbigfloat(x::NumberResult) = x.tag == BIGFLOAT end end end - if isfloat || opts.allownan + + if isfloat if opts.allownan # check for NaN, Inf, -Inf @check_special(opts.nan, NaN) diff --git a/test/parse.jl b/test/parse.jl index bbea56b..6a4234d 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -187,6 +187,11 @@ end foo::String = "bar" end +#struct for parsing typemax Int test +struct TestAllownanInt + a::Int64 +end + # example from JSON.parse docstring abstract type AbstractMonster end @@ -406,7 +411,25 @@ JSON.lift(::DateMaterializedObjectStyle, ::Type{Date}, x::JSON.Object) = Date(x[ @test_throws ArgumentError JSON.parse("trub") # allownan for parsing normally invalid json values @test JSON.parse("NaN"; allownan=true) === NaN - @test JSON.parse("Inf"; inf="Inf", allownan=true) === Inf + @test JSON.parse("Infinity"; allownan=true) === Inf + @test JSON.parse("-Infinity"; allownan=true) === -Inf + @test JSON.parse("Inf"; allownan=true) === Inf + @test JSON.parse("-Inf"; allownan=true) === -Inf + # Nested version + @test isequal(JSON.parse("[Inf,NaN,-Infinity]"; allownan=true), [Inf, NaN, -Inf]) + # allownan with typemax Int + @test JSON.parse(string(typemax(Int)), Int; allownan=true) === typemax(Int) + @test JSON.parse(string(typemax(UInt64)), UInt64; allownan=true) === typemax(UInt64) + @test JSON.parse(string(typemax(Int64)), Int64; allownan=true) === typemax(Int64) + @test JSON.parse(string(typemin(Int64)), Int64; allownan=true) === typemin(Int64) + @test JSON.parse(string(typemax(Int64)); allownan=true) === typemax(Int64) + @test JSON.parse(string(typemax(Int128)), Int128; allownan=true) === typemax(Int128) + @test JSON.parse(string(2^53 + 1); allownan=true) === Int64(2^53 + 1) + #allownan with typemax in struct + @test JSON.parse("{\"a\":$(typemax(Int64))}", TestAllownanInt; allownan=true).a === typemax(Int64) + #Test that parsing "-" and "+" with allownan=true throws an error + @test_throws ArgumentError JSON.parse("-"; allownan=true) + @test_throws ArgumentError JSON.parse("+"; allownan=true) # jsonlines support @test JSON.parse("1"; jsonlines=true) == [1] @test JSON.parse("1 \t"; jsonlines=true) == [1]