`ZonedDateTime` loses information about zone id (Default Value Change for 4.x?)

Open
#6,348 6 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
66/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
java
Domain
backend

Research direction

The issue includes a JUnit reproduction using JsonMapper and ZonedDateTime; start by locating the Java time serializers and deserializers in the repository and their existing tests. Run the relevant tests, then add coverage for preserving the Europe/Berlin zone id during JSON writing and parsing. Done means the reproduced round trip and expected JSON assertions pass.

Written by the indexing model from the issue text.

Description

4.x date-time-config
Search before asking
  • I searched in the issues and found nothing similar.
Describe the bug

The following tests all fail with jackson 3.1.8 and 3.2.4.

Writing JSON omits the ZoneId from the output.

Parsing JSON normalizes the ZoneId to UTC.

Both is wrong since the ZoneId is the entire difference between ZonedDateTime and OffsetDateTime and must not get lost.

Version Information

jackson 3.1.8 and 3.2.4

Reproduction
import org.junit.jupiter.api.Test;
import tools.jackson.databind.json.JsonMapper;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Objects;

import static org.junit.jupiter.api.Assertions.assertEquals;

class JacksonTest {

    private static final JsonMapper JSON_MAPPER =
            JsonMapper.builder()
                    .build();

    private static final ZonedDateTime ZONED_DATE_TIME = ZonedDateTime.of(
            2026, 10, 29,
            13, 12, 0, 666161,
            ZoneId.of("Europe/Berlin")
    );

    private static final Example EXAMPLE_INSTANCE = new Example(ZONED_DATE_TIME);

    private static final String EXPECTED_JSON_STRING =
            "{\"zonedDateTime\":\"2026-10-29T13:12:00.000666161+01:00[Europe/Berlin]\"}";

    @Test
    void creatingAndParsingJsonWorks() {

        String jsonString = JSON_MAPPER.writeValueAsString(EXAMPLE_INSTANCE);

        Example result = JSON_MAPPER.readValue(jsonString, Example.class);

        assertEquals(EXAMPLE_INSTANCE, result);
    }

    @Test
    void creatingJsonWorks() {
        String jsonString = JSON_MAPPER.writeValueAsString(EXAMPLE_INSTANCE);

        assertEquals(
                EXPECTED_JSON_STRING,
                jsonString
        );
    }

    @Test
    void parsingJsonWorks() {
        Example parsed = JSON_MAPPER.readValue(
                EXPECTED_JSON_STRING,
                Example.class);

        assertEquals(
                EXAMPLE_INSTANCE,
                parsed
        );
    }

    public static final class Example {
        private ZonedDateTime zonedDateTime;

        public Example() {
            this(null);
        }

        public Example(ZonedDateTime zonedDateTime) {
            this.zonedDateTime = zonedDateTime;
        }

        public ZonedDateTime getZonedDateTime() {
            return zonedDateTime;
        }

        public void setZonedDateTime(ZonedDateTime zonedDateTime) {
            this.zonedDateTime = zonedDateTime;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null || getClass() != o.getClass()) return false;
            Example example = (Example) o;
            return Objects.equals(zonedDateTime, example.zonedDateTime);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(zonedDateTime);
        }

        @Override
        public String toString() {
            return "Example{" +
                    "zonedDateTime=" + zonedDateTime +
                    '}';
        }
    }
}
Expected behavior

All tests should be green.

Dominant language
Java
Stars
3.8k
Forks
1.6k
Avg merge
1d 18h
Merged PRs (30d)
59

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from FasterXML/jackson-databind

All issues in FasterXML/jackson-databind

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.