don't serialize BigInteger/BigDecimal as strings in jsonb
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..28c85b8 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
@@ -56,6 +56,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
@@ -234,6 +236,10 @@
Integer.parseInt(it.toString()))
.ifPresent(builder::setSnippetMaxLength);
+ // drop johnzon-mapper BigInteger/BigDecimal built in adapters to not serialize those types as JsonString. See JSON-B spec 3.4.1
+ builder.getAdapters().remove(new AdapterKey(BigDecimal.class, String.class));
+ builder.getAdapters().remove(new AdapterKey(BigInteger.class, String.class));
+
// user adapters
final Types types = new Types();
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
index 089f99b..49e4c25 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
@@ -21,6 +21,8 @@
import static org.junit.Assert.assertEquals;
import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.time.Duration;
@@ -63,7 +65,8 @@
final LocalDate localDate = LocalDate.of(2015, 1, 1);
final LocalTime localTime = LocalTime.of(1, 2, 3);
final LocalDateTime localDateTime = LocalDateTime.of(2015, 1, 1, 1, 1);
- final String expected = "{\"calendar\":\"2015-01-01T01:01:00Z[UTC]\",\"date\":\"2015-01-01T01:01:00Z[UTC]\"," +
+ final String expected = "{\"bigDecimal\":1.5,\"bigInteger\":1," +
+ "\"calendar\":\"2015-01-01T01:01:00Z[UTC]\",\"date\":\"2015-01-01T01:01:00Z[UTC]\"," +
"\"duration\":\"PT30S\",\"gregorianCalendar\":\"2015-01-01T01:01:00Z[UTC]\"," +
"\"instant\":\"2015-01-01T00:00:00Z\",\"localDate\":\"2015-01-01\"," +
"\"localDateTime\":\"2015-01-01T01:01\",\"localTime\":\"01:02:03\"," +
@@ -97,6 +100,8 @@
assertEquals(TimeUnit.DAYS.toMillis(localDate.toEpochDay()), types.instant.toEpochMilli());
assertEquals(Duration.of(30, ChronoUnit.SECONDS), types.duration);
assertEquals(Period.of(0, 1, 10), types.period);
+ assertEquals(BigInteger.valueOf(1), types.bigInteger);
+ assertEquals(BigDecimal.valueOf(1.5), types.bigDecimal);
assertEquals(expected, jsonb.toJson(types));
@@ -172,6 +177,8 @@
private LocalDate localDate;
private OffsetDateTime offsetDateTime;
private OffsetTime offsetTime;
+ private BigInteger bigInteger;
+ private BigDecimal bigDecimal;
public LocalTime getLocalTime() {
return localTime;
@@ -341,6 +348,22 @@
this.offsetTime = offsetTime;
}
+ public BigInteger getBigInteger() {
+ return bigInteger;
+ }
+
+ public void setBigInteger(BigInteger bigInteger) {
+ this.bigInteger = bigInteger;
+ }
+
+ public BigDecimal getBigDecimal() {
+ return bigDecimal;
+ }
+
+ public void setBigDecimal(BigDecimal bigDecimal) {
+ this.bigDecimal = bigDecimal;
+ }
+
@Override
public boolean equals(final Object o) {
if (this == o) {
@@ -369,7 +392,9 @@
Objects.equals(localDateTime, types.localDateTime) &&
Objects.equals(localDate, types.localDate) &&
Objects.equals(offsetDateTime, types.offsetDateTime) &&
- Objects.equals(offsetTime, types.offsetTime);
+ Objects.equals(offsetTime, types.offsetTime) &&
+ Objects.equals(bigInteger, types.bigInteger) &&
+ Objects.equals(bigDecimal, types.bigDecimal);
}
@Override
@@ -377,7 +402,7 @@
return Objects.hash(
url, uri, optionalString, optionalInt, optionalLong, optionalDouble, date,
calendar, gregorianCalendar, timeZone, zoneId, zoneOffset, simpleTimeZone, instant, duration,
- period, localDateTime, localDate, offsetDateTime, offsetTime);
+ period, localDateTime, localDate, offsetDateTime, offsetTime, bigInteger, bigDecimal);
}
}
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/map/LazyConverterMap.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/map/LazyConverterMap.java
index f1a4e42..9c12067 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/map/LazyConverterMap.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/map/LazyConverterMap.java
@@ -55,6 +55,7 @@
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
@@ -63,6 +64,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
@@ -93,6 +95,13 @@
private boolean useShortISO8601Format = true;
private DateTimeFormatter dateTimeFormatter;
+ private List<AdapterKey> builtInAdapterKeys = Stream.of(Date.class, URI.class, URL.class, Class.class, String.class,
+ BigDecimal.class, BigInteger.class, Locale.class, Period.class, Duration.class, Calendar.class, GregorianCalendar.class,
+ TimeZone.class, ZoneId.class, ZoneOffset.class, SimpleTimeZone.class, Instant.class, LocalDateTime.class, LocalDate.class,
+ ZonedDateTime.class, OffsetDateTime.class, OffsetTime.class, LocalTime.class)
+ .map(it -> new AdapterKey(it, String.class, true))
+ .collect(Collectors.toList());
+
public void setUseShortISO8601Format(final boolean useShortISO8601Format) {
this.useShortISO8601Format = useShortISO8601Format;
}
@@ -102,6 +111,15 @@
}
@Override
+ public Adapter<?, ?> remove(Object key) {
+ if (key instanceof AdapterKey) {
+ builtInAdapterKeys.remove(key);
+ }
+
+ return super.remove(key);
+ }
+
+ @Override
public Adapter<?, ?> get(final Object key) {
final Adapter<?, ?> found = super.get(key);
if (found == NO_ADAPTER) {
@@ -112,7 +130,7 @@
return null;
}
final AdapterKey k = AdapterKey.class.cast(key);
- if (k.getTo() == String.class) {
+ if (builtInAdapterKeys.contains(k)) {
final Adapter<?, ?> adapter = doLazyLookup(k);
if (adapter != null) {
return adapter;
@@ -132,14 +150,8 @@
}
public Set<AdapterKey> adapterKeys() {
- return Stream.concat(
- super.keySet().stream()
- .filter(it -> super.get(it) != NO_ADAPTER),
- Stream.of(Date.class, URI.class, URL.class, Class.class, String.class, BigDecimal.class, BigInteger.class,
- Locale.class, Period.class, Duration.class, Calendar.class, GregorianCalendar.class, TimeZone.class,
- ZoneId.class, ZoneOffset.class, SimpleTimeZone.class, Instant.class, LocalDateTime.class, LocalDate.class,
- ZonedDateTime.class, OffsetDateTime.class, OffsetTime.class)
- .map(it -> new AdapterKey(it, String.class, true)))
+ return Stream.concat(super.keySet().stream(), builtInAdapterKeys.stream())
+ .filter(it -> super.get(it) != NO_ADAPTER)
.collect(toSet());
}
diff --git a/pom.xml b/pom.xml
index 0828a5b..baf9653 100644
--- a/pom.xml
+++ b/pom.xml
@@ -347,7 +347,7 @@
<property name="ignorePattern" value="@version|@see" />
</module>
<module name="MethodLength">
- <property name="max" value="255" />
+ <property name="max" value="258" />
</module>
<module name="ParameterNumber">
<property name="max" value="13" />