Skip to content

Instantly share code, notes, and snippets.

@mwmitchell
Created August 31, 2021 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mwmitchell/8cd2df3368cd5a7df98064b6f0c00671 to your computer and use it in GitHub Desktop.
Save mwmitchell/8cd2df3368cd5a7df98064b6f0c00671 to your computer and use it in GitHub Desktop.
package com.foo.bar;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class POJOToMapModule extends SimpleModule {
public static void main(String[] args) {
class Foo {
Instant createdAt;
public Foo(Instant createdAt){
this.createdAt = createdAt;
}
public Instant getCreatedAt(){ return createdAt; }
}
Foo foo = new Foo(Instant.now());
ObjectMapper om = new ObjectMapper()
.registerModule(new POJOToMapModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Map<String,Object> map = om.convertValue(foo, om.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class));
System.out.println("createdAt type => " + map.get("createdAt").getClass());
}
public static class InstantToDateSerializer extends JsonSerializer<Instant> {
@Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
// Convert from Instant to Date...
gen.writeObject(Date.from(value));
}
}
}
public static class DateStringToInstantDeserializer extends JsonDeserializer<Object> {
private final JsonDeserializer<?> deserializer;
public DateStringToInstantDeserializer(JsonDeserializer<?> deserializer) {
this.deserializer = deserializer;
}
@Override
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
// The current token is not a string... pass along to the default deserializer:
return deserializer.deserialize(jsonParser, deserializationContext);
}
try {
// It's a string, so let's attempt to parse and if successful, return an Instant.
return Date
.from(LocalDateTime
.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME)
.toInstant(ZoneOffset.UTC));
} catch (DateTimeParseException e) {
// Fallback...
return deserializer.deserialize(jsonParser, deserializationContext);
}
}
}
public POJOToMapModule() {
this.setSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
// Register the Instant to Date serializer if the current field type is an Instant:
if (beanDesc.getBeanClass().isAssignableFrom(Instant.class)) {
return new InstantToDateSerializer();
}
// Fallback to default behavior:
return super.modifySerializer(config, beanDesc, serializer);
}
});
this.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(
DeserializationConfig config,
BeanDescription beanDesc,
JsonDeserializer<?> deserializer
) {
return new DateStringToInstantDeserializer(deserializer);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment