Reputation: 1121
I can't figure why when trying to serialize an object I get an exception which looks related to deserialization. My object has a field which is of joda type LocalDateTime
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(response));
I got the following exception:
org.codehaus.jackson.map.JsonMappingException: java.lang.String cannot be cast to org.joda.time.LocalDateTime
I am trying to serialize. Why it is trying to convert String value to object? I tried to add custom deserializers, but it does not work.
update More of the exception:
org.codehaus.jackson.map.JsonMappingException: java.lang.String cannot be cast to org.joda.time.LocalDateTime (through reference chain: com.my.AccountDetailResponse["registrationDate"])
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097) ~[jackson-mapper-asl-1.9.13.jar:1.9.13]
tried to add deserializer:
CustomDeserializerFactory deserializerFactory = new CustomDeserializerFactory();
deserializerFactory.addSpecificMapping(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.setDeserializerProvider(new StdDeserializerProvider(deserializerFactory));
try {
remoteActionDto.setPayload(mapper.writeValueAsString(response));
} catch (IOException e) {
logger.error("Can not convert response to json!", e);
.....
}
the deserializer itself. I does not convert actually, but only proof of concept:
private static class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return new LocalDateTime();
}
}
Upvotes: 0
Views: 11193
Reputation: 1121
I found the problem (or actually a colleague of mine did it). It is the most stupid java behaviour I've ever met. The problem was, that the DTO which contained the LocalDateTime field was populated via reflection, and it seems possible to successfully set a value of type String
. A class cast exception occurs when you try to use this field (not when it is being set).
public class MyDto {
// trough reflection, the contained object is a java.lang.String
private LocalDateTime myDate;
}
If you ask why this happened - because we haven't configured a converter for LocalDateTime
, but for DateTime
instead. My colleague used LocalDateTime
by mistake and Jackson silently deserialized it as a String
Upvotes: 2
Reputation: 141
Register your mapper with JodaModule module.
mapper.register(new JodaModule())
Or try with JodaMapper:
import com.fasterxml.jackson.datatype.joda.JodaMapper;
public static void main(String args[]){
DateTime dateTime = new DateTime(12353434);
JodaMapper mapper = new JodaMapper();
try {
serializedString = mapper.writeValueAsString(dateTime);
System.out.println(serializedString);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
Console Output:
12353434
Upvotes: 0
Reputation: 2764
I've written a quick test class to check what you've provided. It seems to run fine and output the following:
{"value":[2014,2,24,13,42,44,745]}
Granted, that may not be the exact format you're looking for, but either way, here is the class:
public class JsonSerialization {
public static void main(final String[] args) {
try {
final Response response = new Response();
final ObjectMapper mapper = new ObjectMapper();
final String value = mapper.writeValueAsString(response);
System.out.println(value);
}
catch (final Exception e) {
e.printStackTrace();
}
}
public static class Response {
LocalDateTime value = new LocalDateTime();
public LocalDateTime getValue() {
return this.value;
}
public void setValue(final LocalDateTime value) {
this.value = value;
}
}
}
I guess this raises the questions:
registrationDate
)?writeValueAsString
method is called within your code?I know this isn't part of your question, but in 1.9.13 of Jackson, you should register custom (de)serializers like so:
SimpleModule module = new SimpleModule("", new Version(1, 0, 0, "");
module.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
Upvotes: 0