This is an automated email from the ASF dual-hosted git repository. jlmonteiro pushed a commit to branch johnzon-1.2.x in repository https://gitbox.apache.org/repos/asf/johnzon.git
commit 164605799273a56d7ffcefc12d49e0913952d734 Author: Jean-Louis Monteiro <jlmonte...@tomitribe.com> AuthorDate: Thu May 11 11:12:44 2023 +0200 fix(JOHNZON-397): Create configuration option to set the BigDecimal scale limit Signed-off-by: Jean-Louis Monteiro <jlmonte...@tomitribe.com> --- .../src/main/java/org/apache/johnzon/core/JsonNumberImpl.java | 6 +++--- .../src/test/java/org/apache/johnzon/core/JsonNumberTest.java | 2 +- .../main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java | 9 ++++++++- .../main/java/org/apache/johnzon/mapper/MapperBuilder.java | 8 +++++++- .../src/main/java/org/apache/johnzon/mapper/MapperConfig.java | 11 +++++++++-- 5 files changed, 28 insertions(+), 8 deletions(-) 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 e5891cf3..4609aceb 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 @@ final class JsonNumberImpl implements JsonNumber, Serializable { @Override public BigInteger bigIntegerValue() { - checkBigIntegerScale(); + checkBigDecimalScale(); return value.toBigInteger(); } @Override public BigInteger bigIntegerValueExact() { - checkBigIntegerScale(); + checkBigDecimalScale(); return value.toBigIntegerExact(); } @@ -120,7 +120,7 @@ final class JsonNumberImpl implements JsonNumber, Serializable { } } - 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 57bbd560..f77773b6 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 @@ public class JsonNumberTest { 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 400dfcfa..46f99177 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 @@ -108,7 +108,10 @@ public class JohnzonBuilder implements JsonbBuilder { // 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")))); @@ -361,6 +364,10 @@ public class JohnzonBuilder implements JsonbBuilder { 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 ef4ca516..013742cb 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 @@ public class MapperBuilder { 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; @@ -233,7 +234,7 @@ public class MapperBuilder { treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite, accessMode, encoding, attributeOrder, failOnUnknownProperties, serializeValueFilter, useBigDecimalForFloats, deduplicateObjects, - interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers, + interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers, maxBigDecimalScale, supportEnumContainerDeserialization, typeLoader, discriminatorMapper, discriminator, deserializationPredicate, serializationPredicate, @@ -530,6 +531,11 @@ public class MapperBuilder { 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 1bc01752..813e61c6 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 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { 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; @@ -116,6 +116,7 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { 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, @@ -127,7 +128,7 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { 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()))); } @@ -150,6 +151,7 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { 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, @@ -172,6 +174,7 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { this.encoding = encoding; this.useJsRange = useJsRange; this.useBigDecimalForObjectNumbers = useBigDecimalForObjectNumbers; + this.maxBigDecimalScale = maxBigDecimalScale; this.supportEnumMapDeserialization = supportEnumMapDeserialization; this.typeLoader = typeLoader; this.discriminatorMapper = discriminatorMapper; @@ -238,6 +241,10 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable { return useBigDecimalForObjectNumbers; } + public int getMaxBigDecimalScale() { + return maxBigDecimalScale; + } + public boolean isUseJsRange() { return useJsRange; }