diff --git a/.gitignore b/.gitignore
index c7431be0..fbc2e096 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
.gradle
build/
+.out-of-scope/
+.omo/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
diff --git a/build.gradle b/build.gradle
index c4fce8dd..676d31ad 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ plugins {
id 'pmd'
id 'checkstyle'
id 'org.owasp.dependencycheck' version '13.0.0'
- id 'org.cyclonedx.bom' version '3.4.1'
+ id 'org.cyclonedx.bom' version '3.5.0'
id 'info.solidsoft.pitest' version '1.19.0'
id 'net.ltgt.errorprone' version '5.1.1'
}
@@ -47,17 +47,21 @@ tasks.withType(org.gradle.api.publish.maven.tasks.PublishToMavenRepository).conf
}
java {
- // Only enforce toolchain in CI to ensure consistent Java 21 builds
+ // Only enforce toolchain in CI to ensure consistent Java 17 builds
// Locally, use whatever JDK is installed
if (System.getenv('CI') == 'true') {
toolchain {
- languageVersion = JavaLanguageVersion.of(21)
+ languageVersion = JavaLanguageVersion.of(17)
}
}
withSourcesJar()
withJavadocJar()
}
+tasks.withType(JavaCompile).configureEach {
+ options.release = 17
+}
+
repositories {
mavenCentral()
mavenLocal()
@@ -172,6 +176,7 @@ tasks.checkstyleTest {
dependencies {
implementation 'tools.jackson.core:jackson-databind:3.2.3'
implementation 'tools.jackson.module:jackson-module-blackbird:3.2.3'
+ implementation 'tech.uom.lib:ryu:1.0.0'
compileOnly 'com.github.spotbugs:spotbugs-annotations:4.10.4'
// NullAway + Error Prone for compile-time null safety
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 47492140..e7f8e36a 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -52,6 +52,11 @@
+
+
+
+
+
@@ -62,6 +67,11 @@
+
+
+
+
+
@@ -91,6 +101,14 @@
+
+
+
+
+
+
+
+
@@ -99,6 +117,14 @@
+
+
+
+
+
+
+
+
@@ -107,6 +133,14 @@
+
+
+
+
+
+
+
+
@@ -115,11 +149,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -128,6 +175,14 @@
+
+
+
+
+
+
+
+
@@ -136,16 +191,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -316,6 +389,14 @@
+
+
+
+
+
+
+
+
@@ -334,6 +415,11 @@
+
+
+
+
+
@@ -484,6 +570,14 @@
+
+
+
+
+
+
+
+
@@ -514,6 +608,11 @@
+
+
+
+
+
@@ -670,6 +769,11 @@
+
+
+
+
+
@@ -1018,6 +1122,11 @@
+
+
+
+
+
@@ -1043,6 +1152,11 @@
+
+
+
+
+
@@ -1173,6 +1287,11 @@
+
+
+
+
+
@@ -1292,16 +1411,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1325,6 +1462,14 @@
+
+
+
+
+
+
+
+
@@ -1486,11 +1631,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1499,6 +1657,14 @@
+
+
+
+
+
+
+
+
@@ -1507,6 +1673,14 @@
+
+
+
+
+
+
+
+
@@ -1515,6 +1689,14 @@
+
+
+
+
+
+
+
+
@@ -1523,6 +1705,14 @@
+
+
+
+
+
+
+
+
@@ -1551,6 +1741,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1559,6 +1762,14 @@
+
+
+
+
+
+
+
+
@@ -1567,6 +1778,14 @@
+
+
+
+
+
+
+
+
@@ -1575,6 +1794,14 @@
+
+
+
+
+
+
+
+
@@ -1583,6 +1810,14 @@
+
+
+
+
+
+
+
+
@@ -1638,6 +1873,11 @@
+
+
+
+
+
@@ -1646,6 +1886,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1654,6 +1910,14 @@
+
+
+
+
+
+
+
+
@@ -1662,6 +1926,14 @@
+
+
+
+
+
+
+
+
@@ -1670,6 +1942,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1678,6 +1974,14 @@
+
+
+
+
+
+
+
+
@@ -1807,6 +2111,11 @@
+
+
+
+
+
@@ -1833,6 +2142,14 @@
+
+
+
+
+
+
+
+
@@ -1883,6 +2200,14 @@
+
+
+
+
+
+
+
+
@@ -1907,6 +2232,14 @@
+
+
+
+
+
+
+
+
@@ -1923,6 +2256,14 @@
+
+
+
+
+
+
+
+
@@ -1931,11 +2272,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1962,6 +2316,11 @@
+
+
+
+
+
@@ -2009,6 +2368,14 @@
+
+
+
+
+
+
+
+
@@ -2017,11 +2384,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2402,6 +2782,14 @@
+
+
+
+
+
+
+
+
@@ -2620,6 +3008,14 @@
+
+
+
+
+
+
+
+
@@ -2652,6 +3048,14 @@
+
+
+
+
+
+
+
+
@@ -2662,6 +3066,11 @@
+
+
+
+
+
@@ -2677,6 +3086,11 @@
+
+
+
+
+
diff --git a/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java b/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java
index c674ddd7..ac0e02bf 100644
--- a/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java
+++ b/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java
@@ -3,6 +3,7 @@
import dev.toonformat.jtoon.util.StringEscaper;
import dev.toonformat.jtoon.util.StringValidator;
import org.jspecify.annotations.Nullable;
+import tech.uom.lib.ryu.Ryu;
import tools.jackson.databind.JsonNode;
import java.math.BigDecimal;
import java.util.Collection;
@@ -75,11 +76,11 @@ private static String encodeNumber(final JsonNode value) {
return value.asString();
}
- // Use decimalValue() for exact precision from Jackson's DecimalNode,
- // avoiding precision loss from double conversion.
- // BigDecimal.valueOf(double) uses Double.toString which can only
- // represent ~15-17 significant digits.
- final BigDecimal decimal = value.decimalValue();
+ // Use Ryu for shortest round-trip digits (spec ยง4.2).
+ // BigDecimal.valueOf(double) uses Double.toString which only delivers
+ // shortest digits from JDK 19+ (JDK-4511638). Ryu provides the same
+ // output on Java 17.
+ final BigDecimal decimal = new BigDecimal(Ryu.doubleToString(value.doubleValue()));
final String plainString = decimal.toPlainString();
// Strip trailing zeros but preserve the number's mathematical value