Skip to content

Commit 56f31ed

Browse files
authored
Merge pull request #353 from avaje/feature/npe-custom-serializer
Fix NPE when custom JsonAdapter (not nullSafe()) is registered via Supplier
2 parents 965dda8 + c6e7956 commit 56f31ed

File tree

6 files changed

+98
-2
lines changed

6 files changed

+98
-2
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.example.other.custom.serializer;
2+
3+
import io.avaje.jsonb.Json;
4+
5+
import java.math.BigDecimal;
6+
7+
@Json
8+
public record CustomExample2(
9+
@Json.Serializer(MoneySerializer2.class)
10+
BigDecimal amountOwed,
11+
BigDecimal somethingElse) {}

blackbox-test/src/main/java/org/example/other/custom/serializer/MoneySerializer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
@CustomAdapter(global = false)
1313
public class MoneySerializer implements JsonAdapter<BigDecimal> {
1414

15+
/** Constructor takes Jsonb, registered via AdapterBuilder */
1516
public MoneySerializer(Jsonb jsonb) {}
1617

1718
@Override
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.example.other.custom.serializer;
2+
3+
import io.avaje.json.JsonAdapter;
4+
import io.avaje.json.JsonReader;
5+
import io.avaje.json.JsonWriter;
6+
import io.avaje.jsonb.CustomAdapter;
7+
8+
import java.math.BigDecimal;
9+
import java.math.RoundingMode;
10+
11+
@CustomAdapter(global = false)
12+
public class MoneySerializer2 implements JsonAdapter<BigDecimal> {
13+
14+
/** Default constructor -> registered via {@code Supplier<JsonAdapter>} */
15+
public MoneySerializer2() { }
16+
17+
@Override
18+
public BigDecimal fromJson(JsonReader reader) {
19+
return reader.readDecimal().setScale(2, RoundingMode.DOWN);
20+
}
21+
22+
@Override
23+
public void toJson(JsonWriter writer, BigDecimal value) {
24+
writer.value(value.setScale(2, RoundingMode.DOWN));
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.example.other.custom.serializer;
2+
3+
import io.avaje.jsonb.JsonType;
4+
import io.avaje.jsonb.Jsonb;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.math.BigDecimal;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
/** Uses MoneySerializer2 which is registered via Supplier */
12+
class SelectiveCustomSerializerSupplierTest {
13+
14+
Jsonb jsonb = Jsonb.builder().build();
15+
JsonType<CustomExample2> jsonType = jsonb.type(CustomExample2.class);
16+
17+
@Test
18+
void toFromJson() {
19+
final var bean = new CustomExample2(new BigDecimal("100.95630"), new BigDecimal("100.95630"));
20+
21+
final String asJson = jsonType.toJson(bean);
22+
assertThat(asJson).isEqualTo("{\"amountOwed\":100.95,\"somethingElse\":100.95630}");
23+
24+
final var fromJson = jsonType.fromJson(asJson);
25+
assertThat(fromJson.amountOwed()).isEqualTo(new BigDecimal("100.95"));
26+
assertThat(fromJson.somethingElse()).isEqualTo(new BigDecimal("100.95630"));
27+
assertThat(fromJson).isNotEqualTo(bean);
28+
}
29+
30+
@Test
31+
void toFromJson_with_null() {
32+
final var bean = new CustomExample2(null, null);
33+
34+
final String asJson = jsonType.toJson(bean);
35+
assertThat(asJson).isEqualTo("{}");
36+
37+
final var fromJson = jsonType.fromJson(asJson);
38+
assertThat(fromJson.amountOwed()).isNull();
39+
assertThat(fromJson.somethingElse()).isNull();
40+
assertThat(fromJson).isEqualTo(bean);
41+
}
42+
43+
}

blackbox-test/src/test/java/org/example/other/custom/serializer/CustomExampleTest.java renamed to blackbox-test/src/test/java/org/example/other/custom/serializer/SelectiveCustomSerializerTest.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import io.avaje.jsonb.JsonType;
1010
import io.avaje.jsonb.Jsonb;
1111

12-
class TestSelectiveSerializer {
12+
/** Uses MoneySerializer which is registered via AdapterBuilder */
13+
class SelectiveCustomSerializerTest {
1314

1415
Jsonb jsonb = Jsonb.builder().build();
1516
JsonType<CustomExample> jsonType = jsonb.type(CustomExample.class);
@@ -26,4 +27,18 @@ void toFromJson() {
2627
assertThat(fromJson.somethingElse()).isEqualTo(new BigDecimal("100.95630"));
2728
assertThat(fromJson).isNotEqualTo(bean);
2829
}
30+
31+
@Test
32+
void toFromJson_with_null() {
33+
final var bean = new CustomExample(null, null);
34+
35+
final String asJson = jsonType.toJson(bean);
36+
assertThat(asJson).isEqualTo("{}");
37+
38+
final var fromJson = jsonType.fromJson(asJson);
39+
assertThat(fromJson.amountOwed()).isNull();
40+
assertThat(fromJson.somethingElse()).isNull();
41+
assertThat(fromJson).isEqualTo(bean);
42+
}
43+
2944
}

jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ static <T> AdapterFactory newAdapterFactory(Type type, JsonAdapter<T> jsonAdapte
346346
static <T> AdapterFactory newAdapterFactory(Type type, Supplier<JsonAdapter<T>> jsonAdapter) {
347347
requireNonNull(type);
348348
requireNonNull(jsonAdapter);
349-
return (targetType, jsonb) -> simpleMatch(type, targetType) ? jsonAdapter.get() : null;
349+
return (targetType, jsonb) -> simpleMatch(type, targetType) ? jsonAdapter.get().nullSafe() : null;
350350
}
351351

352352
static AdapterFactory newAdapterFactory(Type type, AdapterBuilder builder) {

0 commit comments

Comments
 (0)