Skip to content

Generic class with generic field of runtime type Double is deserialized as BigDecimal when used with @JsonTypeInfo and JsonTypeInfo.As.EXISTING_PROPERTY #3251

@BaesKevin

Description

@BaesKevin

Describe the bug

Bug appears when deserializing a generic class with a generic field with runtime type double, and the generic class
is annotated with @JsonTypeInfo with @JsonTypeInfo with JsonTypeInfo.As.EXISTING_PROPERTY.
The bug does not occur when using @JsonTypeInfo with JsonTypeInfo.As.PROPERTY.

Version information

  • bug exists in 2.12.4
  • bug does not exist in 2.11.3
  • Java version: 16

To Reproduce

Test with 1 succeeding and 1 failing case, expecting both to succeed.

package com.test;

import static org.assertj.core.api.Assertions.assertThat;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import org.junit.Test;

public class JacksonMapperDeserializesDoubleAsDoubleTest {

    private final ObjectMapper objectMapper = new MyObjectMapper();

    static class MyObjectMapper extends ObjectMapper {
        public MyObjectMapper() {
            registerModule(new Jdk8Module());
            // this is default, set it to be sure
            configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, false);
        }
    }

    @Test
    public void deserializesDoubleToDouble_givenJsonTypeInfoUsingNewProperty() throws JsonProcessingException {
        GenericWrapperWithNewProperty<?> wrapper = new GenericWrapperWithNewProperty<>(123.45);

        String json = objectMapper.writeValueAsString(wrapper);
        GenericWrapperWithNewProperty<?> actualWrapper = objectMapper.readValue(json, GenericWrapperWithNewProperty.class);

        assertThat(actualWrapper).satisfies(it -> assertThat(it.getValue()).isEqualTo(123.45));
        assertThat(json).contains("\"value\":123.45");
    }

    @Test
    public void deserializesDoubleToDouble_givenJsonTypeInfoUsingExistingProperty() throws JsonProcessingException {
        GenericWrapperWithExistingProperty<?> wrapper = new GenericWrapperWithExistingProperty<>(123.45);

        String json = objectMapper.writeValueAsString(wrapper);
        GenericWrapperWithExistingProperty<?> actualWrapper = objectMapper.readValue(json, GenericWrapperWithExistingProperty.class);

        assertThat(actualWrapper).satisfies(it -> assertThat(it.getValue()).isEqualTo(123.45));
        assertThat(json).contains("\"value\":123.45");
    }

    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "type_alias"
    )
    static class GenericWrapperWithNewProperty<T> {
        private final T value;

        @JsonCreator
        public GenericWrapperWithNewProperty(@JsonProperty("value") T value) {
            this.value = value;
        }

        public T getValue() {
            return value;
        }
    }

// @JsonSubtypes or using abstract classes and such is not required to reproduce the issue
    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "fieldType",
        visible = true,
        defaultImpl = GenericWrapperWithExistingProperty.class
    )
    static class GenericWrapperWithExistingProperty<T> {
        private String fieldType;
        private final T value;

        @JsonCreator
        public GenericWrapperWithExistingProperty(@JsonProperty("value") T value) {
            this.value = value;
        }

        public T getValue() {
            return value;
        }

        public String getFieldType() {
            return fieldType;
        }

        public void setFieldType(String fieldType) {
            this.fieldType = fieldType;
        }
    }
}

Additional context

This bug started happening when upgrading Spring Boot from 2.4.1 to 2.5.3.
As we don't manage Jackson version ourselves, Jackson was upgraded to 2.12.4,
I have not tried to reproduce this issue with a project that has only Jackson dependencies, managed
by jackson BOM 2.12.4.

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