diff --git a/src/main/java/com/ankurm/jackson3/part4custom/E03SimpleModuleRegistration.java b/src/main/java/com/ankurm/jackson3/part4custom/E03SimpleModuleRegistration.java new file mode 100644 index 0000000..256d8f2 --- /dev/null +++ b/src/main/java/com/ankurm/jackson3/part4custom/E03SimpleModuleRegistration.java @@ -0,0 +1,57 @@ +package com.ankurm.jackson3.part4custom; + +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.module.SimpleModule; + +import java.math.BigDecimal; + +/** + * Post: Custom Serialisers and Mix-ins — https://ankurm.com/jackson-custom-serializer-mixin/ + * Section: "Registering the Serialiser and Deserialiser via SimpleModule" + * + * Jackson 3 differences: + * 1. SimpleModule moved to tools.jackson.databind.module. + * 2. The Version-taking constructor from the post is gone; pass just a name. + * 3. The module is attached with builder.addModule(...), not mapper.registerModule(...), + * because a built mapper is immutable. + */ +public class E03SimpleModuleRegistration { + + public static void main(String[] args) { + SimpleModule moneyModule = new SimpleModule("MoneyModule"); + moneyModule.addSerializer(Money.class, new E01MoneyValueSerializer()); + moneyModule.addDeserializer(Money.class, new E02MoneyValueDeserializer()); + + JsonMapper mapper = JsonMapper.builder() + .addModule(moneyModule) + .build(); + + // Serialise: note the rounding and the upper-casing done by the serialiser. + Money price = new Money(new BigDecimal("19.999"), "usd"); + System.out.println("serialised : " + mapper.writeValueAsString(price)); + + // Deserialise. NOTE: the scale is NOT preserved by default — Jackson parses + // 20.00 as a double first, so you get 20.0 and not 20.00. The blog post claims + // 20.00; that only holds if you turn on USE_BIG_DECIMAL_FOR_FLOATS, below. + Money restored = mapper.readValue("{\"amount\":20.00,\"currency\":\"USD\"}", Money.class); + System.out.println("amount : " + restored.amount() + " (scale lost)"); + + JsonMapper exact = JsonMapper.builder() + .addModule(moneyModule) + .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) + .build(); + System.out.println("amount exact : " + + exact.readValue("{\"amount\":20.00,\"currency\":\"USD\"}", Money.class).amount() + + " (scale preserved)"); + + // The path()-based deserialiser tolerates a missing field; the post's get() + // version would throw NullPointerException here. + Money partial = mapper.readValue("{\"currency\":\"EUR\"}", Money.class); + System.out.println("missing field: " + partial); + + // Without the module the record would serialise structurally instead. + JsonMapper plain = JsonMapper.builder().build(); + System.out.println("no module : " + plain.writeValueAsString(price)); + } +}