Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trailing zeros are stripped when reading BigDecimal as JsonNode #3650

Closed
TeppoLehtonen-TomTom opened this issue Nov 4, 2022 · 2 comments
Closed

Comments

@TeppoLehtonen-TomTom
Copy link

Describe the bug
BigDecimal values are stripping trailing zeros from the JSON source when the concrete type is selected using a custom deserializer (@JsonDeserialize). This differs from the behavior of directly deserializing to the same concrete type, where the trailing zeroes are retained.

Version information
2.13.4.2

To Reproduce

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

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;

class BigDecimalTrailingZeroesTest {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void bigDecimalTrailingZeroes() throws JsonProcessingException {
        // Passes
        assertEquals(
                new BigDecimal("5.00"),
                objectMapper.readValue("{\"value\": 5.00}", BigDecimalHolder.class).getValue());
    }

    @Test
    public void customDeserializedBigDecimalTrailingZeroes() throws JsonProcessingException {
        // org.opentest4j.AssertionFailedError:
        // Expected :5.00
        // Actual   :5.0
        assertEquals(
                new BigDecimal("5.00"),
                objectMapper.readValue("{\"value\": 5.00}", Holder.class).getValue());
    }

    @JsonDeserialize(as = BigDecimalHolder.class)
    private static class BigDecimalHolder implements Holder<BigDecimal> {
        private BigDecimal value;

        public BigDecimal getValue() {
            return value;
        }

        public void setValue(BigDecimal value) {
            this.value = value;
        }
    }

    @JsonDeserialize(using = HolderDeserializer.class)
    private interface Holder<T> {
        T getValue();
    }

    private static class HolderDeserializer extends JsonDeserializer<Holder<?>> {
        @Override
        public Holder<?> deserialize(JsonParser parser, DeserializationContext context)
                throws IOException {
            ObjectMapper mapper = (ObjectMapper) parser.getCodec();
            ObjectNode root = mapper.readTree(parser);
            return mapper.treeToValue(root, BigDecimalHolder.class);
        }
    }
}

Expected behavior
The same behavior in both cases, that the trailing zeroes are retained.

Additional context
This appears to be the very similar to the issue #2784.

@TeppoLehtonen-TomTom TeppoLehtonen-TomTom added the to-evaluate Issue that has been received but not yet evaluated label Nov 4, 2022
@cowtowncoder
Copy link
Member

Difference here is with the handling of ObjectMapper.readTree(), where by default BigDecimal values are "normalized" which strips extra trailing zeroes. It is a feature, not bug, although quite likely unexpected.
The plan is to change this for Jackson 3.0, as per:

https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-2

(see the section for JsonNode).

Now: it is actually possible to change this behavior, although it is not quite as easy as many other features.
Change requires construction of JsonNodeFactory with alternate default:

JsonNodeFactory f = JsonNodeFactory.withExactBigDecimals(true);

and then configuring ObjectMapper with it

objectMapper.setNodeFactory(f);

with this, the exact value will be retained.

@cowtowncoder cowtowncoder removed the to-evaluate Issue that has been received but not yet evaluated label Nov 6, 2022
@cowtowncoder cowtowncoder changed the title Trailing zeros are stripped when deserializing BigDecimal values when using @JsonDeserialize Trailing zeros are stripped when reading BigDecimal as JsonNode Nov 6, 2022
@cowtowncoder
Copy link
Member

I think above explanation shows how to disable trailing-zeroes-stripping; plus #3651 (to be included in 2.15.0) will allow easier configurability. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants