You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using Jackson Databind 2.13.5, annotating a POJO with @JsonDeserialize:
@Getter
@Builder
@ToString
@JsonDeserialize(builder=Person.PersonBuilder.class)
static class Person {
private final String name;
private final List<Pet> pets;
}
@Getter
@Builder
@ToString
static class Pet {
private final String name;
private final String type;
}
takes priority over an explicitly configured deserializer in a mapper:
String serializedPersons = """
name,pets
Ali,"[{'Cutesy','cat'}, {'Tootsie','cat'}]"
Jan,"[{'Mr. Bubbles','dog'}, {'Lilly','cat'}]"
Tom,"[{'Fester','dog'}, {'Wednesday','cat'}]"
Zoe,"[{'Jaeger','dog'}, {'Deira','cat'}]"
""";
CsvMapper mapper = new CsvMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Person.class, new PersonSerializer());
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);
CsvSchema schema = mapper.schemaFor(Person.class).withHeader();
ObjectReader reader = mapper.readerFor(Person.class).with(schema);
MappingIterator<Person> i = reader.readValues(serializedPersons);
while (i.hasNext()) {
System.out.println("Person: " + i.next());
}
It seems like explicitly configured serializers & deserializers on the mappers should take precedence over others that are discovered.
In my case, I have network marshalled objects that should be using annotated builder, and CLI applications that should be using their own explicitly configured deserializers. I wrote a question on SO before I found the problem.
public class JacksonTest {
@Test
public void writeJson() throws JsonProcessingException {
var mapper = new ObjectMapper();
var writer = mapper.writer();
System.out.println(writer.writeValueAsString(_single()));
System.out.println(writer.writeValueAsString(_multiple()));
}
@Test
public void writeJsonObjectsIndividually() throws IOException {
var mapper = new ObjectMapper();
var writer = new StringWriter();
try (var seqWriter = mapper.writerFor(Person.class).writeValues(writer)) {
seqWriter.write(_single());
seqWriter.writeAll(_multiple());
}
System.out.println(writer.toString());
}
@Test
public void writePersonToCsv() throws IOException {
CsvMapper mapper = new CsvMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Person.class, new PersonSerializer());
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);
var writer = new StringWriter();
CsvSchema schema = mapper.schemaFor(Person.class)
.withHeader();
try (var seqWriter = mapper.writerWithSchemaFor(Person.class).with(schema).writeValues(writer)) {
seqWriter.write(_single());
seqWriter.writeAll(_multiple());
}
System.out.println(writer.toString());
}
@Test
public void deserializePets() {
String serializedPets = "[{'Mr. Bubbles','dog'}, {'Lilly','cat'}]";
List<Pet> pets = PersonDeserializer.deserialize(serializedPets);
assertThat(pets).hasSize(2);
}
@Test
public void readPersonFromCsv() throws IOException {
String serializedPersons = """
name,pets
Ali,"[{'Cutesy','cat'}, {'Tootsie','cat'}]"
Jan,"[{'Mr. Bubbles','dog'}, {'Lilly','cat'}]"
Tom,"[{'Fester','dog'}, {'Wednesday','cat'}]"
Zoe,"[{'Jaeger','dog'}, {'Deira','cat'}]"
""";
CsvMapper mapper = new CsvMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Person.class, new PersonSerializer());
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);
CsvSchema schema = mapper.schemaFor(Person.class).withHeader();
ObjectReader reader = mapper.readerFor(Person.class).with(schema);
MappingIterator<Person> i = reader.readValues(serializedPersons);
while (i.hasNext()) {
System.out.println("Person: " + i.next());
}
}
@Getter
@Builder
@ToString
//This will take precedence over mapper registered deserializers
@JsonDeserialize(builder=Person.PersonBuilder.class)
static class Person {
private final String name;
private final List<Pet> pets;
}
@Getter
@Builder
@ToString
static class Pet {
private final String name;
private final String type;
}
static class PersonSerializer extends StdSerializer<Person> {
private static final long serialVersionUID = 1L;
public PersonSerializer() {
this(Person.class);
}
public PersonSerializer(Class<Person> type) {
super(type);
}
@Override
public void serialize(Person value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("name", value.getName());
jgen.writeStringField("pets", _toString(value.getPets()));
jgen.writeEndObject();
}
private String _toString(List<Pet> pets) {
return Arrays.toString(pets.stream()
.map(PersonSerializer::serialize)
.toArray(String[]::new));
}
private static String serialize(Pet pet) {
return String.format("{'%s','%s'}", pet.name, pet.type);
}
}
static class PersonDeserializer extends StdDeserializer<Person> {
private static final long serialVersionUID = 1L;
public PersonDeserializer() {
this(Person.class);
}
public PersonDeserializer(Class<Person> type) {
super(type);
}
@Override
public Person deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String name = node.get("name").asText();
String petsSerialized = node.get("pets").asText();
List<Pet> pets = deserialize(petsSerialized);
return Person.builder().name(name).pets(pets).build();
}
private static List<Pet> deserialize(String serializedPets) {
return Arrays.stream(serializedPets.replaceAll("^.\\{?|}?.$", "").split("},\s*\\{"))
.map(inner -> Arrays.stream(inner.replaceAll("^.'?|'?.$", "").split("','")).toList())
.map(l -> deserialize(l))
.collect(Collectors.toList());
}
private static Pet deserialize(List<String> l) {
return Pet.builder().name(l.get(0)).type(l.get(1)).build();
}
}
private static Person _single() {
return Person.builder().name("Jan").pets(List.of(Pet.builder().name("Mr. Bubbles").type("dog").build(), Pet.builder().name("Lilly").type("cat").build())).build();
}
private static Person[] _multiple() {
return List.of(_single(), _single(), _single()).toArray(Person[]::new);
}
}
The text was updated successfully, but these errors were encountered:
JanStureNielsen
changed the title
@JsonDeserialize(builder=<class>) prioritized over addDeserializer(<instance>)@JsonDeserialize prioritized over addDeserializerApr 29, 2023
Using Jackson Databind 2.13.5, annotating a POJO with
@JsonDeserialize
:takes priority over an explicitly configured deserializer in a mapper:
It seems like explicitly configured serializers & deserializers on the mappers should take precedence over others that are discovered.
In my case, I have network marshalled objects that should be using annotated builder, and CLI applications that should be using their own explicitly configured deserializers. I wrote a question on SO before I found the problem.
The text was updated successfully, but these errors were encountered: