Chiraag Mundhe
Chiraag Mundhe

Reputation: 384

Prevent Jackson from serializing a float as a double

Jackson seems to be coercing all floats into doubles in any data structure that I am trying to serialize into JSON. Is there any way to avoid this behavior?

Float f = 50.1f;
System.out.println(f);                                 // 50.1
System.out.println(f.doubleValue());                   // 50.099998474121094
System.out.println(new ObjectMapper().valueToTree(f)); // 50.099998474121094 -- how to prevent this?

Using jackson-all-1.9.11.jar.

Upvotes: 4

Views: 6348

Answers (2)

armagedescu
armagedescu

Reputation: 2155

In Jackson 2.17.2 this is not a problem, but as a problem still might appear in unexpected places:

    float f = 4.24f;
    double d = 4.24;
    System.out.println (omp.valueToTree(f));
    System.out.println (omp.valueToTree(d));

And the result, so far looks ok:

4.24
4.24

Yet, it might require some additional formatting.
Some problems still might occur. But these problems come from Java, not from the Jackson itself. Supposing having following class

public class Amount {
    private float amount;
    public void setAmount(float amount){this.amount = amount;}
    public float getAmount(){return amount;}
}

As with Jackson it might occur like this

    @Test
    void testAmount() throws JsonProcessingException {
        Amount amt = new ObjectMapper().readValue("{\"amount\":4.24}", Amount.class);
        assertEquals(4.24, amt.getAmount()); //<-- test fails here
    }

enter image description here

Fixing this by using correct datatype, using 4.24f instead of 4.24 works:

    @Test
    void testAmount() throws JsonProcessingException {
        Amount amt = new ObjectMapper().readValue("{\"amount\":4.24}", Amount.class);
        assertEquals(4.24f, amt.getAmount()); //<-- this is Ok
    }

And the problem is not in Jackson but it is a normal behavior for Java itself

    @Test
    void doubleTest()
    {
        float f = 4.24f;
        double d = 4.24;
        assertEqualsDescribe(4.24, f, "expected to fail");
        assertEqualsDescribe((float)4.24, f, "expected to succeed");
        assertEqualsDescribe(4.24f, f, "expected to succeed");
        assertEqualsDescribe(4.24f, d, "expected to fail");
        assertEqualsDescribe(4.24, d, "expected to succeed");
        assertEqualsDescribe((double)4.24f, d, "fails regardless of expectancies");
        assertEqualsDescribe(f, d, "expected to fail");
        assertEqualsDescribe(f, (float)d, "expected to succeed");
        assertEqualsDescribe((double)f, d, "expected to succeed");
    }

enter image description here

Here is the helper code for the describe assert:

...
    public static final String RESET = "\033[0m";  // Text Reset
    public static final String RED   = "\033[0;31m";   // RED
    public static final String GREEN = "\033[0;32m";   // GREEN
    public static final String CYAN  = "\033[0;36m";   // CYAN
    public static <T1, T2> void assertEqualsDescribe(T1 val1, T2 val2, String message) {
        if (val1.equals(val2))
            System.out.print ("Success: " + GREEN + val1 + " equals " + val2 + RESET);
        else
            System.out.print ("Fail: " + RED + val1 + " doesn't equal " + val2 + RESET);
        if (message != null) System.out.print ( CYAN + " " + message + RESET);
        System.out.println();
    }
...

Upvotes: 0

Santhosh Gandhe
Santhosh Gandhe

Reputation: 6970

You can use the custom Jackson serializer of your own as described in this link

Java to Jackson JSON serialization: Money fields

Upvotes: 0

Related Questions