The question is published on by Tutorial Guruji team.
I’m planning to use Lombok for creating hundreds of classes that are based on “value object” pattern as follows:
@Data public final class SomeId implements Serializable { private final long value; }
And I want to use these classes for JSON serialization powered by Jackson. for example, consider a DTO class as follows:
public class SomeDTO { SomeId id; public SomeId getId() { return id; } }
I want that DTO class to be serialized as something like {"id":123}
, but Jackson produces something like {"id":{"value":123}}
, which comes with unnecessary nested object with a field named value
. i.e. a testcase expresses my requirement:
public class SomeDTOTest { @Test public void serializationTest() throws Exception { SomeDTO dto = new SomeDTO(); dto.id = new SomeId(123); String serialized = new ObjectMapper().writeValueAsString(dto); System.out.println(serialized); // {"id":{"value":123}} assertThat(serialized, is("{"id":123}")); // I want {"id":123} instead! } }
I know putting @JsonValue
annotation to every getValue()
method in SomeId
classes would be a solution, but I can’t do it because there is no actual definition of @Data
classes because Lombok automatically creates it.
Creating actual getValue()
method annotated as @JsonValue
for every classes by hand might be another solution but it means creating tons of boilarplate code.
How do I achieve this requirement without boilerplate code?
Answer
You can write custom Serializer for this class.
E.g.:
class CustomSerializer extends StdSerializer<SomeId>{ protected CustomSerializer(Class<SomeId> t) { super(t); } @Override public void serialize(SomeId someId, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { gen.writeNumber(someId.getValue()); } }
Now use this serializer to serialize SomeId
class:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(new CustomSerializer(SomeId.class)); mapper.registerModule(module); SomeDTO dto = new SomeDTO(); dto.id = new SomeId(123); String serialized = mapper.writeValueAsString(dto); System.out.println(serialized); // output : {"id":123}