FasterXML / jackson-datatype-joda

Extension module to properly support full datatype set of Joda datetime library
Apache License 2.0
140 stars 82 forks source link

jackson.databind.JsonMappingException: Can not construct instance of org.joda.time.Chronology #84

Closed sdk451 closed 8 years ago

sdk451 commented 8 years ago

I've set up my jackson ObjectMapper and registered an instance of JodaModule.

Working with jongo. I have an class B which extends A, where A is a class whose source I don't control and which contains several joda.DateTime objects. I can serialise B objects down to my Mongo database.

However, when my code I attempts to unmarshall B, I get the following exception:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.joda.time.Chronology, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information at [Source: de.undercouch.bson4jackson.io.LittleEndianInputStream@1315176; pos: 148](through reference chain: B["creationTime"]->org.joda.time.DateTime["iChronology"])

Isn't the JodaModule meant to handle this without any further annotation or custom serializer / deserializer?

wattazoum commented 8 years ago

Hi,

I would suggest that you provide a Unit test showing your problem. I think I understand what you mean but nothing it better than a bit of code.

sdk451 commented 8 years ago

It's not so easy to write unit tests in my environment, but it would something like this:

    public class A
    {
        DateTime aDate;

        public A()
        {
            aDate = new DateTime(2014, 12, 20, 2, 30, DateTimeZone.forID("Europe/London"));
        }

        public DateTime getADate()
        {
            return aDate;
        }
    }

    public class B extends A
    {
        String uuid;

        public B()
        {
            super();
            uuid = "foobar";
        }

        public String getUuid()
        { 
            return uuid;
        }
    }

    @Test
    public void whenSerializingJodaTime_thenCorrect() 
    throws JsonProcessingException 
    {

        B b = new B();

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        String result = mapper.writeValueAsString(b);
        assertThat(result, containsString("2014-12-20T02:30:00.000Z"));

    }
wattazoum commented 8 years ago

Hi,

I wrote the unit test as you suggested, but it doesn't fail. What is your version of :

sdk451 commented 8 years ago

jackson-datatype-joda - 2.7.4 not certain about joda.time. I'll force my play build to take on joda-time 2.7 and see if that makes any difference.

sdk451 commented 8 years ago

Seem to have resolved the problem. Thank you for your help!

cowtowncoder commented 8 years ago

@sdk451 glad you got it working, although now I am bit worried as it is unclear as to what the underlying issue was... such problems have a habit of returning. But at least good it is not blocking you.

wattazoum commented 8 years ago

My optinion is that there was a conflict of version between his version of Joda and the datatype serializer.

sdk451 commented 8 years ago

I think that's the likely cause. Joda.time has recently changed the way it handles calendars (Chronology) which includes areally vasts amoutn of information (not a choice I would have made). The deserializer seemed to struggle that - mostly likely the contents of Chronology changed between version of Joda.time

On Wed, Jun 1, 2016 at 6:24 AM, Oumar Aziz OUATTARA < notifications@github.com> wrote:

My optinion is that there was a conflict of version between his version of Joda and the datatype serializer.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/FasterXML/jackson-datatype-joda/issues/84#issuecomment-222808848, or mute the thread https://github.com/notifications/unsubscribe/AQUFaYSavKqAZ6ZrGnPyvisdDIWmRWUAks5qHJjvgaJpZM4IpQyn .

cowtowncoder commented 8 years ago

Ok good to know. If there was a way to make deserializer more tolerant I would like to do that, but it seems like it may not be something Jackson directly interacts with? I have tried to slowly progress version of Joda time being depended on to try to reduce possibility of breakage, but that only goes so far.

danielemaddaluno commented 6 years ago

I solved that issue adding this line, objectMapper.registerModule(new JodaModule());, when creating my ObjectMapper:

private static ObjectMapper createObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule s = new SimpleModule();
    objectMapper.registerModule(s);
    objectMapper.registerModule(new JodaModule());
    return objectMapper;
}
anilkonduru commented 4 years ago

@danielemaddaluno objectMapper.registerModule(new JodaModule()); worked. Thank you.

amreldeeb0 commented 4 years ago

can you please tell where should I add this line objectMapper.registerModule(new JodaModule()) As I don't have any mappers, I get this when I call a microservice internally from another service. they both have the same model object which has the DateTime attribute.

danielemaddaluno commented 4 years ago

I have something like this:

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;

@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {
    @Override
    public ObjectMapper getContext(Class<?> type) {
        return JsonUtils.getObjectMapper();
    }
}

where JsonUtils:

import java.util.List;

import org.joda.money.BigMoney;
import org.joda.time.DateTime;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.TypeFactory;

public abstract class JsonUtils {
    static ObjectMapper om = createObjectMapper();

    public static <T> T fromString(String value) {
        try {
            return om.readValue(value, new TypeReference<T>() {
            });
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> T fromString(String value, Class<T> clazz) {
        try {
            return om.readValue(value, clazz);
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> List<T> fromStringList(String value, Class<T> clazz) {
        try {
            TypeFactory typeFactory = om.getTypeFactory();
            return om.readValue(value, typeFactory.constructCollectionType(List.class, clazz));
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> String toString(T value) {
        try {
            return om.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            return "{}";
        }
    }

    public static ObjectMapper getObjectMapper() {
        return om;
    }

    private static ObjectMapper createObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule s = new SimpleModule();
        objectMapper.registerModule(s);
        objectMapper.registerModule(new JodaModule());
        // other configurations...
        return objectMapper;
    }

}

Check this out for more: http://stackoverflow.com/a/27347445/3138238