fix(JOHNZON-397): Create configuration option to set the BigDecimal scale limit
Signed-off-by: Jean-Louis Monteiro <jlmonteiro@tomitribe.com>
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
index 73443ea..60fd4a8 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
@@ -69,13 +69,13 @@
@Override
public BigInteger bigIntegerValue() {
- checkBigIntegerScale();
+ checkBigDecimalScale();
return value.toBigInteger();
}
@Override
public BigInteger bigIntegerValueExact() {
- checkBigIntegerScale();
+ checkBigDecimalScale();
return value.toBigIntegerExact();
}
@@ -120,7 +120,7 @@
}
}
- private void checkBigIntegerScale() {
+ private void checkBigDecimalScale() {
// should be fine enough. Maybe we should externalize so users can pick something better if they need to
// it becomes their responsibility to fix the limit and may expose them to a DoS attack
final int limit = 1_000;
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
index 57e824c..334a142 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
@@ -100,7 +100,7 @@
long start = System.nanoTime();
for (int i = 1; i < 100; i++) {
// if it takes a second in any machine, that's already too much
- // depends on the allowed scale in JsonNumberImpl#checkBigIntegerScale
+ // depends on the allowed scale in JsonNumberImpl#checkBigDecimalScale
if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) > (30 * i)) {
fail("took too long: " + TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) + " s" +
" to compute " + i + " conversions toBigInteger");
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 278e814..3275da0 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -110,7 +110,10 @@
// todo: global spec toggle to disable all these ones at once?
builder.setUseBigDecimalForObjectNumbers(
- config.getProperty("johnzon.use-big-decimal-for-object").map(this::toBool).orElse(true));
+ config.getProperty("johnzon.use-big-decimal-for-object").map(this::toBool).orElse(true));
+ builder.setMaxBigDecimalScale(
+ config.getProperty("johnzon.max-big-decimal-scale").map(this::toInt).orElse(1000));
+
builder.setSupportEnumContainerDeserialization( // https://github.com/eclipse-ee4j/jakartaee-tck/issues/103
toBool(System.getProperty("johnzon.support-enum-container-deserialization", config.getProperty("johnzon.support-enum-container-deserialization")
.map(String::valueOf).orElse("true"))));
@@ -368,6 +371,10 @@
return !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v);
}
+ private Integer toInt(final Object v) {
+ return !Integer.class.isInstance(v) ? Integer.parseInt(v.toString()) : Integer.class.cast(v);
+ }
+
private AccessMode toAccessMode(final Object s) {
if (String.class.isInstance(s)) {
try {
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 91e6cd5..6fa89ad 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -104,6 +104,7 @@
private Boolean deduplicateObjects = null;
private boolean useJsRange;
private boolean useBigDecimalForObjectNumbers;
+ private int maxBigDecimalScale = 1000;
private boolean supportEnumContainerDeserialization = true;
private Function<Class<?>, MapperConfig.CustomEnumConverter<?>> enumConverterFactory = type -> new EnumConverter(type);
private boolean skipAccessModeWrapper;
@@ -234,7 +235,7 @@
treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite,
accessMode, encoding, attributeOrder, failOnUnknownProperties,
serializeValueFilter, useBigDecimalForFloats, deduplicateObjects,
- interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers,
+ interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers, maxBigDecimalScale,
supportEnumContainerDeserialization,
typeLoader, discriminatorMapper, discriminator,
deserializationPredicate, serializationPredicate,
@@ -531,6 +532,11 @@
return this;
}
+ public MapperBuilder setMaxBigDecimalScale(final int maxBigDecimalScale) {
+ this.maxBigDecimalScale = maxBigDecimalScale;
+ return this;
+ }
+
public MapperBuilder setSupportEnumContainerDeserialization(final boolean supportEnumContainerDeserialization) {
this.supportEnumContainerDeserialization = supportEnumContainerDeserialization;
return this;
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
index dd0ab71..23b78dc 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
@@ -81,7 +81,7 @@
private final Boolean deduplicateObjects;
private final Map<Class<?>, Class<?>> interfaceImplementationMapping;
private final boolean useBigDecimalForObjectNumbers;
-
+ private int maxBigDecimalScale;
private final Function<String, Class<?>> typeLoader;
private final Function<Class<?>, String> discriminatorMapper;
private final Predicate<Class<?>> serializationPredicate;
@@ -118,6 +118,7 @@
final Map<Class<?>, Class<?>> interfaceImplementationMapping,
final boolean useJsRange,
final boolean useBigDecimalForObjectNumbers,
+ final int maxBigDecimalScale,
final boolean supportEnumMapDeserialization,
final Function<String, Class<?>> typeLoader,
final Function<Class<?>, String> discriminatorMapper,
@@ -129,7 +130,7 @@
this(adapters, objectConverterWriters, objectConverterReaders, version, close, skipNull, skipEmptyArray,
treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite, accessMode, encoding,
attributeOrder, failOnUnknown, serializeValueFilter, useBigDecimalForFloats, deduplicateObjects, interfaceImplementationMapping,
- useJsRange, useBigDecimalForObjectNumbers, supportEnumMapDeserialization, typeLoader,
+ useJsRange, useBigDecimalForObjectNumbers, maxBigDecimalScale, supportEnumMapDeserialization, typeLoader,
discriminatorMapper, discriminator, deserializationPredicate, serializationPredicate, enumConverterFactory,
JohnzonCores.snippetFactory(50, Json.createGeneratorFactory(emptyMap())), null);
}
@@ -152,6 +153,7 @@
final Map<Class<?>, Class<?>> interfaceImplementationMapping,
final boolean useJsRange,
final boolean useBigDecimalForObjectNumbers,
+ final int maxBigDecimalScale,
final boolean supportEnumMapDeserialization,
final Function<String, Class<?>> typeLoader,
final Function<Class<?>, String> discriminatorMapper,
@@ -175,6 +177,7 @@
this.encoding = encoding;
this.useJsRange = useJsRange;
this.useBigDecimalForObjectNumbers = useBigDecimalForObjectNumbers;
+ this.maxBigDecimalScale = maxBigDecimalScale;
this.supportEnumMapDeserialization = supportEnumMapDeserialization;
this.typeLoader = typeLoader;
this.discriminatorMapper = discriminatorMapper;
@@ -243,6 +246,10 @@
return useBigDecimalForObjectNumbers;
}
+ public int getMaxBigDecimalScale() {
+ return maxBigDecimalScale;
+ }
+
public boolean isUseJsRange() {
return useJsRange;
}