Skip to content
New issue

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

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

Already on GitHub? # 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.

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

No branches or pull requests

2 participants