package com.ankurm.jackson3.part4custom; import tools.jackson.core.JsonGenerator; import tools.jackson.databind.SerializationContext; import tools.jackson.databind.ValueSerializer; import tools.jackson.databind.json.JsonMapper; import tools.jackson.databind.module.SimpleModule; /** * BEYOND THE POST — the rename that breaks every custom handler on upgrade. * * Jackson 2's JsonSerializer/JsonDeserializer are gone. The Jackson 3 names * are ValueSerializer/ValueDeserializer. Extending ValueSerializer directly * (rather than StdSerializer) is the leanest form and shows the rename plainly. */ public class E05ValueSerializerDirect { public record UserId(String value) { } /** Renders the wrapper as a bare JSON string rather than {"value":"..."}. */ static class UserIdSerializer extends ValueSerializer { @Override public void serialize(UserId id, JsonGenerator gen, SerializationContext ctxt) { gen.writeString(id.value()); } } public record Ticket(UserId assignee, String title) { } public static void main(String[] args) { SimpleModule module = new SimpleModule("UserIdModule"); module.addSerializer(UserId.class, new UserIdSerializer()); JsonMapper mapper = JsonMapper.builder().addModule(module).build(); System.out.println("custom : " + mapper.writeValueAsString(new Ticket(new UserId("u-42"), "Fix build"))); System.out.println("default : " + JsonMapper.builder().build() .writeValueAsString(new Ticket(new UserId("u-42"), "Fix build"))); System.out.println("base class: " + UserIdSerializer.class.getSuperclass().getName()); } }