0

I am learning to use Jackson's custom serialization and deserialization capabilities to handle the DatePair class. I hope to concatenate the fields of DatePair into a single string.
Here is a MCVE code:
DatePair is a unmodifiable class within a third-party library:

 import lombok.Data; import java.util.Date; @Data public class DatePair { Date date1; Date date2; } 

My example:

 import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; import lombok.Data; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; @Data public class Example { @Data public static class Model1 { @JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss.SSS", timezone = "GMT+2") DatePair datePair; } public static class DatePairJsonSerializer extends JsonSerializer<DatePair> { @Override public void serialize(DatePair value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeRaw("("); serializers.defaultSerializeValue(value.date1, gen); gen.writeRaw(", "); /* When serialize Model1 will throw JsonGenerationException: Can not write a string, expecting field name (context: Object) */ serializers.defaultSerializeValue(value.date2, gen); gen.writeRaw(")"); } } public static void main(String[] args) { ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(DatePair.class, new DatePairJsonSerializer()); mapper.registerModule(simpleModule); DatePair datePair = new DatePair(); datePair.setDate1(new Date()); datePair.setDate2(new Date()); Model1 model1 = new Model1(); model1.setDatePair(datePair); try { /* serialize DatePair */ String json = mapper.writeValueAsString(datePair); System.out.println(json); // output: ("2025-06-22 10:02:48", "2025-06-22 10:02:48") /* serialize Model1 will throw JsonGenerationException: Can not write a string, expecting field name (context: Object) */ json = mapper.writeValueAsString(model1); // expected output: {"datePair": "(2025/06/22 10:02:48.000, 2025/06/22 10:02:48.000)"} System.out.println(json); } catch (Exception e) { e.printStackTrace(); } } } 

dependencies:

 <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.18.2</version> </dependency> 

I encountered some issues:

  1. When serializing DatePair alone, I want the output Date to ​​not have quotes​​, like: (2025-06-22 10:02:48, 2025-06-22 10:02:48), instead of ("2025-06-22 10:02:48", "2025-06-22 10:02:48")
  2. When serializing Model1, I want @JsonFormat applied to the date fields in DatePair
  3. Current serialization of Model1 throws errors. How to resolve?
  4. Could you provide a deserialization example matching the serialization logic?
1
  • Try writing the " that should surround your ( enclosed dates as well, looks like currently you are missing those. Commented Jun 22 at 3:59

2 Answers 2

0

Jackson's serialization might be tricky. You can achieve your goal by StdConverter.

Here's an example:

@Data public static class Model1 { @JsonSerialize(converter = DatePairSerializerConverter.class) @JsonDeserialize(converter = DatePairDeserializerConverter.class) DatePair datePair; } public static class DatePairSerializerConverter extends StdConverter<DatePair, String> { private static final DateFormat FIRST_DATE_FORMAT = new SimpleDateFormat("(yyyy/MM/dd HH:mm:ss.SSS, "); private static final DateFormat SECOND_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS)"); @Override public String convert(DatePair datePair) { return FIRST_DATE_FORMAT.format(datePair.date1) + SECOND_DATE_FORMAT.format(datePair.date2); } } public static class DatePairDeserializerConverter extends StdConverter<String, DatePair> { private static final String DELIMITER = ", "; private static final DateFormat FIRST_DATE_FORMAT = new SimpleDateFormat("(yyyy/MM/dd HH:mm:ss.SSS"); private static final DateFormat SECOND_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS)"); @Override public DatePair convert(String value) { String[] dates = value.split(DELIMITER); DatePair datePair = new DatePair(); try { datePair.setDate1(FIRST_DATE_FORMAT.parse(dates[0])); datePair.setDate2(SECOND_DATE_FORMAT.parse(dates[1])); return datePair; } catch (ParseException e) { throw new RuntimeException(e); } } } 

A few side notes:

  1. If you want to register DatePairSerializerConverter & DatePairDeserializerConverter globally (so you don't need to specify @JsonSerialize & @JsonDeserialize in each model explicitly), you might need to look into StdDelegatingSerializer & StdDelegatingDeserializer, because there's no such method as objectMapper.addConverter(new DatePairSerializerConverter()), unfortunatelly.
  2. It's recommended to store each class in a separate file.
  3. It's recommended to add private modifier to the fields your model classes.
  4. If you're on Java 17+, try migrating your model classes to record, so you don't have to bother with Lombok annotations.
Sign up to request clarification or add additional context in comments.

Comments

0

First, the output ("2025-06-22 10:02:48", "2025-06-22 10:02:48") of serialized DatePair is not a standard JSON, that mean's you can not using SerializerProvider.defaultSerializeValue . You need create a format with JsonFormator define a default, and the Serializer (recommended extends StdSerializer) should implements ContextualSerializer. You can refer to the implementation of DateSerializer and DateTimeSerializerBase.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.