Skip to content

Can't deserialize a serialized DateTimeZone with default typing #82

@strmer15

Description

@strmer15

Trying to serialize a DateTimeZone instance, then deserialize it back afterwards; it always fails. Looks like it's due to the fact that there is no type mapping for CachedDateTimeZone (indeed for any of the subclasses of DateTimeZone) and no String constructor, combined with our project's use of default typing on serialized objects.

package com.rw;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.DateTimeZone;
import org.junit.Assert;
import org.junit.Test;

public class TestTimeZone {

    @Test
    public void testTimeZoneSerialization() throws Exception {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        objectMapper.registerModule(new JodaModule());

        final DateTimeZone timeZone = DateTimeZone.forID("America/New_York");
        final String json = objectMapper.writeValueAsString(timeZone);

        final DateTimeZone timeZoneRead = objectMapper.readValue(json, DateTimeZone.class);

        Assert.assertNotNull(timeZoneRead.getID());
        Assert.assertEquals("America/New_York", timeZoneRead.getID());
    }
}

Result:

com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class org.joda.time.tz.CachedDateTimeZone] from String value ('America/New_York'); no single-String constructor/factory method
 at [Source: ["org.joda.time.tz.CachedDateTimeZone","America/New_York"]; line: 1, column: 40]

Obviously, a simple workaround is to create a mix-in just for DateTimeZone that disables typing only for it. The following test passes:

package com.rw;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.DateTimeZone;
import org.junit.Assert;
import org.junit.Test;

public class TestTimeZone {

    @Test
    public void testTimeZoneSerialization() throws Exception {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.addMixIn(DateTimeZone.class, DateTimeZoneMixin.class);

        objectMapper.registerModule(new JodaModule());

        final DateTimeZone timeZone = DateTimeZone.forID("America/New_York");
        final String json = objectMapper.writeValueAsString(timeZone);

        final DateTimeZone timeZoneRead = objectMapper.readValue(json, DateTimeZone.class);

        Assert.assertNotNull(timeZoneRead.getID());
        Assert.assertEquals("America/New_York", timeZoneRead.getID());
    }

    @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
    public interface DateTimeZoneMixin {

    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions