Skip to content

Fix #1239: Add support for non-finite values in schema and data#1240

Closed
mjcarman wants to merge 3 commits intonetworknt:masterfrom
mjcarman:master
Closed

Fix #1239: Add support for non-finite values in schema and data#1240
mjcarman wants to merge 3 commits intonetworknt:masterfrom
mjcarman:master

Conversation

@mjcarman
Copy link
Copy Markdown

@mjcarman mjcarman commented Apr 1, 2026

Modifies numeric validators to add checks for non-finite values and process them as Double instead of BigDecimal (which would trigger an exception).

Implements #1239

Note: In order to run the test for these changes, you'll need jackson-dataformats-yaml v3.2 (currently pre-release). In particular, you need the changes in FasterXML/jackson-dataformats-text#627, which added support for properly parsing .inf, -.inf, and .nan in YAML files.

mjcarman added 3 commits April 1, 2026 17:46
BigDecimal can't represent non-finite values (±Infinity and NaN). Add
checks for nodes containing non-finite floating-point values to numeric
validators. Process such values as double/Double/DoubleNode instead.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for non-finite numeric values (Infinity, -Infinity, NaN) when validating YAML-derived schemas and instances, avoiding BigDecimal conversion failures.

Changes:

  • Extend numeric threshold validators (minimum/maximum and exclusive variants) to treat NaN as a validation failure.
  • Update enum and multipleOf handling to safely process non-finite instance values.
  • Add a YAML-focused regression test suite covering const, enum, min/max, and multipleOf with non-finite values.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/test/java/com/networknt/schema/NonFiniteTest.java Adds regression tests for YAML .inf, -.inf, .nan across several numeric keywords.
src/main/java/com/networknt/schema/keyword/MultipleOfValidator.java Rejects non-finite floating-point instance values to avoid BigDecimal conversion errors.
src/main/java/com/networknt/schema/keyword/MinimumValidator.java Treats NaN as crossing the minimum threshold (validation error).
src/main/java/com/networknt/schema/keyword/MaximumValidator.java Treats NaN as crossing the maximum threshold (validation error).
src/main/java/com/networknt/schema/keyword/ExclusiveMinimumValidator.java Treats NaN as crossing the exclusive minimum threshold (validation error).
src/main/java/com/networknt/schema/keyword/ExclusiveMaximumValidator.java Treats NaN as crossing the exclusive maximum threshold (validation error).
src/main/java/com/networknt/schema/keyword/EnumValidator.java Normalizes non-finite numbers as DoubleNode for enum comparisons.
src/main/java/com/networknt/schema/keyword/ConstValidator.java Adds special handling for NaN comparisons in const.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 37 to +57
if (schemaNode.isNumber() && node.isNumber()) {
if (schemaNode.decimalValue().compareTo(node.decimalValue()) != 0) {
if (((NumericNode) schemaNode).isNaN() || ((NumericNode) node).isNaN()) {
// At least one of the nodes is a non-finite floating-point number and therefore not representable as BigDecimal.
if (Double.isNaN(schemaNode.doubleValue())) {
// Treat `const: .nan` in schema as meaning "isNaN()"
// because NaN != anything (including itself) per IEEE 754.
if (!Double.isNaN(node.doubleValue())) {
executionContext.addError(error().instanceNode(node).instanceLocation(instanceLocation)
.evaluationPath(executionContext.getEvaluationPath())
.locale(executionContext.getExecutionConfig().getLocale())
.arguments(schemaNode.asString(schemaNode.toString()), node.asString(node.toString())).build());
}
}
else if (schemaNode.doubleValue() != node.doubleValue()) {
executionContext.addError(error().instanceNode(node).instanceLocation(instanceLocation)
.evaluationPath(executionContext.getEvaluationPath())
.locale(executionContext.getExecutionConfig().getLocale())
.arguments(schemaNode.asString(schemaNode.toString()), node.asString(node.toString())).build());
}
}
else if (schemaNode.decimalValue().compareTo(node.decimalValue()) != 0) {
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const numeric comparison still falls back to decimalValue() for infinities because the non-finite guard only checks NumericNode.isNaN(). Infinity/-Infinity are not NaN, and decimalValue()/BigDecimal conversion for those values is likely to throw, breaking validation for schemas/data containing .inf/-.inf (the new test covers this).

Consider broadening the guard to treat any non-finite floating-point number (NaN or ±Infinity) using isFloatingPointNumber() + !Double.isFinite(doubleValue()), and then compare using doubleValue() (keeping the special-case semantics for NaN). Also update the comment to match the condition.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +24
private final static SchemaRegistry REGISTRY = SchemaRegistry.withDialect(Dialects.getDraft202012());
private final static String YAML_STRING =
"""
---
- 10.0
- 50.0
- .inf
- -.inf
- .nan
""";
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test relies on YAML parsing of .inf, -.inf, and .nan, but the current build uses tools.jackson ${version.jackson} (pom.xml currently sets it to 3.1.0) for jackson-dataformat-yaml. Per the PR description, that parsing support only exists in jackson-dataformats-yaml 3.2+, so CI will likely fail unless the dependency is bumped (or the test is made conditional/disabled when unsupported).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants