From 03750bbf34430956460496a8664b93e69e5f87bb Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Sun, 4 Oct 2026 12:37:24 -0600 Subject: [PATCH] Validate integer-valued floating-point inputs consistently Apply the existing zero-fraction check to AbstractFloat and cover public scalar, nullable, property, and array validation. AI disclosure: This work was prepared with assistance from OpenAI Codex. --- src/validation.jl | 2 +- test/integer_floats.jl | 41 +++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/integer_floats.jl diff --git a/src/validation.jl b/src/validation.jl index cf3fdf8..cb671ca 100644 --- a/src/validation.jl +++ b/src/validation.jl @@ -584,7 +584,7 @@ _is_type(::Any, ::Val) = false _is_type(::Array, ::Val{:array}) = true _is_type(::Bool, ::Val{:boolean}) = true _is_type(::Integer, ::Val{:integer}) = true -_is_type(x::Float64, ::Val{:integer}) = isinteger(x) +_is_type(x::AbstractFloat, ::Val{:integer}) = isinteger(x) _is_type(::Real, ::Val{:number}) = true _is_type(::Nothing, ::Val{:null}) = true _is_type(::Missing, ::Val{:null}) = true diff --git a/test/integer_floats.jl b/test/integer_floats.jl new file mode 100644 index 0000000..1e0ec11 --- /dev/null +++ b/test/integer_floats.jl @@ -0,0 +1,41 @@ +@testset "Integer-valued floating-point instances" begin + integer = JSONSchema.Schema(Dict("type" => "integer")) + nullable = JSONSchema.Schema(Dict("type" => ["integer", "null"])) + number = JSONSchema.Schema(Dict("type" => "number")) + object = JSONSchema.Schema( + Dict("properties" => Dict("count" => Dict("type" => "integer"))), + ) + array = JSONSchema.Schema(Dict("items" => Dict("type" => "integer"))) + + for T in (Float16, Float32, Float64, BigFloat) + for value in (zero(T), -zero(T), T(7), T(-2)) + @test isvalid(integer, value) + @test isvalid(nullable, value) + end + for value in (T(0.5), T(-2.5), T(NaN), T(Inf), T(-Inf)) + @test !isvalid(integer, value) + @test !isvalid(nullable, value) + end + @test isvalid(number, T(0.5)) + @test isvalid(object, Dict("count" => T(2))) + issue = JSONSchema.validate(object, Dict("count" => T(0.5))) + @test issue.reason == "type" + @test JSONSchema.json_pointer(issue) == "#/count" + @test isvalid(array, T[1, 2]) + issue = JSONSchema.validate(array, T[1, 1.5]) + @test issue.reason == "type" + @test JSONSchema.json_pointer(issue) == "#/1" + end + + @test isvalid(integer, BigFloat(big(2)^200)) + @test isvalid(integer, big(2)^200) + @test isvalid(integer, 7) + @test isvalid(nullable, nothing) + @test isvalid(nullable, missing) + for value in (true, false, "7", nothing) + @test !isvalid(integer, value) + end + for value in (true, false) + @test !isvalid(number, value) + end +end diff --git a/test/runtests.jl b/test/runtests.jl index 3e3f654..3ef77c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,6 +13,7 @@ import OrderedCollections import ZipFile include("additional_patterns.jl") +include("integer_floats.jl") const TEST_SUITE_URL = "https://github.com/json-schema-org/JSON-Schema-Test-Suite/archive/23.1.0.zip"