question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scale of deserialized BigDecimal are not always the same

See original GitHub issue

Hi,

When I use the annotation @JsonUnwrapped to materialize a component bean, the scale of the BigDecimal deserialized is different. I’ve written a test case below to reproduce the issue. Is there a way to control the scale of BigDecimal? Do I have to configure a custom deserializer?

(Test case reproduced with Jacskon 2.4.0 and 1.9.13 on Java 6)

Thanks,

Benoit

import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;

import java.math.BigDecimal;

public class BigDecimalScaleTest {

    private String json = "{" +
            "  \"name\": \"Ben\"," +
            "  \"first\": 12.00," +
            "  \"second\": 14.00" +
            "}";

    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void testScale() throws Exception {

        MyDomain myDomain = objectMapper.readValue(json, MyDomain.class);

        MyFlatDomain myFlatDomain = objectMapper.readValue(json, MyFlatDomain.class);

        Assert.assertEquals(myDomain.getName(), myFlatDomain.getName());
        Assert.assertEquals(myDomain.getFirst(), myFlatDomain.getFirst()); // 12.00 = 12.00
        Assert.assertEquals(myDomain.getInnerDomain().getSecond(), myFlatDomain.getSecond());
         // 14.0 != 14.00
    }

    private static class MyDomain {
        private String name;
        private BigDecimal first;
        @JsonUnwrapped
        private MyInnerDomain innerDomain;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public BigDecimal getFirst() {
            return first;
        }

        public void setFirst(BigDecimal first) {
            this.first = first;
        }

        public MyInnerDomain getInnerDomain() {
            return innerDomain;
        }

        public void setInnerDomain(MyInnerDomain innerDomain) {
            this.innerDomain = innerDomain;
        }
    }

    private static class MyInnerDomain {
        private BigDecimal second;

        public BigDecimal getSecond() {
            return second;
        }

        public void setSecond(BigDecimal second) {
            this.second = second;
        }
    }

    private static class MyFlatDomain {
        private String name;
        private BigDecimal first;
        private BigDecimal second;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public BigDecimal getFirst() {
            return first;
        }

        public void setFirst(BigDecimal first) {
            this.first = first;
        }

        public BigDecimal getSecond() {
            return second;
        }

        public void setSecond(BigDecimal second) {
            this.second = second;
        }
    }

}

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Reactions:2
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

8reactions
azzoticommented, Sep 7, 2015

Reproduced with jackson 2.5.1 Workaround possible with simple Deserializer:

public class MoneyDeserializer extends JsonDeserializer<BigDecimal> {

    private NumberDeserializers.BigDecimalDeserializer delegate = NumberDeserializers.BigDecimalDeserializer.instance;

    @Override
    public BigDecimal deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        BigDecimal bd = delegate.deserialize(jp, ctxt);
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd;
    }    
}

Then us the deserializer like this to make the test pass

private static class MyInnerDomain {
    @JsonDeserialize(using=MoneyDeserializer.class)
    private BigDecimal second;
1reaction
cowtowncodercommented, Jul 2, 2020

@mjustin Please file a new issue (with possible ref to this as background); I do not usually re-open closed issues as that complicates release notes significantly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Jackson annotation to convert BigDecimal value and set scale ...
I want to have the BigDecimal value up to 2 decimal place only. Is there any annotation exist using which I can directly...
Read more >
BigDecimal (Java Platform SE 8 ) - Oracle Help Center
Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale.
Read more >
Java static code analysis: "BigDecimal(double)" should not be ...
One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1,...
Read more >
Jackson: set BigDecimal as type for JSON deserialization of ...
As we can see, this time the actual type of the “value” field of the object created as a result of JSON deserialization...
Read more >
DeserializationFeature (jackson-databind 2.9.0 API) - FasterXML
If enabled such values will be deserialized as BigDecimal s; if disabled, ... if not, default value is used (0 for 'int', 0.0...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found