I want to serialize a Map with Jackson. The Date should be serialized as a timestamp, like all my other dates.
The following code renders the keys in the form "Tue Mar 11 00:00:00 CET 1952" (which is Date.toString()) instead of the timestamp.
Map<Date, String> myMap = new HashMap<Date, String>(); ... ObjectMapper.writeValue(myMap)
I assume this is because of type erasure and jackson doesn't know at runtime that the key is a Date. But I didn't find a way to pass a TypeReference to any writeValue method.
Is there a simple way to achieve my desired behaviour or are all keys always rendered as Strings by jackson?
Thanks for any hint.
How to deserialize Date from JSON using Jackson. In order to correct deserialize a Date field, you need to do two things: 1) Create a custom deserializer by extending StdDeserializer<T> class and override its deserialize(JsonParser jsonparser, DeserializationContext context) method.
We can format a date using the setDateFormat() of ObjectMapper class. This method can be used for configuring the default DateFormat when serializing time values as Strings and deserializing from JSON Strings.
Note that Jackson does not use java.
As already mentioned, Jackson-Datatype-JSR310 provides support for Java 8 Time. You have to register the module like this: ObjectMapper mapper = new ObjectMapper(); mapper.
The default map key serializer is StdKeySerializer
, and it simply does this.
String keyStr = (value.getClass() == String.class) ? ((String) value) : value.toString(); jgen.writeFieldName(keyStr);
You could make use of the SimpleModule feature, and specify a custom key serializer, using the addKeySerializer
method.
And here's how that could be done.
import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.Version; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectWriter; import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.module.SimpleModule; import org.codehaus.jackson.map.type.MapType; import org.codehaus.jackson.map.type.TypeFactory; public class CustomKeySerializerDemo { public static void main(String[] args) throws Exception { Map<Date, String> myMap = new HashMap<Date, String>(); myMap.put(new Date(), "now"); Thread.sleep(100); myMap.put(new Date(), "later"); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(myMap)); // {"Mon Jul 04 11:38:36 MST 2011":"now","Mon Jul 04 11:38:36 MST 2011":"later"} SimpleModule module = new SimpleModule("MyMapKeySerializerModule", new Version(1, 0, 0, null)); module.addKeySerializer(Date.class, new DateAsTimestampSerializer()); MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class); ObjectWriter writer = new ObjectMapper().withModule(module).typedWriter(myMapType); System.out.println(writer.writeValueAsString(myMap)); // {"1309806289240":"later","1309806289140":"now"} } } class DateAsTimestampSerializer extends JsonSerializer<Date> { @Override public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeFieldName(String.valueOf(value.getTime())); } }
Update for the latest Jackson (2.0.4):
import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.TypeFactory; public class CustomKeySerializerDemo { public static void main(String[] args) throws Exception { Map<Date, String> myMap = new HashMap<Date, String>(); myMap.put(new Date(), "now"); Thread.sleep(100); myMap.put(new Date(), "later"); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(myMap)); // {"2012-07-13T21:14:09.499+0000":"now","2012-07-13T21:14:09.599+0000":"later"} SimpleModule module = new SimpleModule(); module.addKeySerializer(Date.class, new DateAsTimestampSerializer()); MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class); ObjectWriter writer = new ObjectMapper().registerModule(module).writerWithType(myMapType); System.out.println(writer.writeValueAsString(myMap)); // {"1342214049499":"now","1342214049599":"later"} } } class DateAsTimestampSerializer extends JsonSerializer<Date> { @Override public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeFieldName(String.valueOf(value.getTime())); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With