Skip to content

Inconsistent behavior deserializing boxed and collections of Double when the input contains no decimal #49

@joshuaprince

Description

@joshuaprince

Describe the bug
ConfigLib handles reading and loading Doubles without a decimal point a bit inconsistently depending on whether they are primitive, boxed, or part of a collection.

To Reproduce
Here's a complete set of tests that show the inconsistent behavior:

    // YamlConfigurationsTest.java
    @Configuration
    private static final class DoublesConfig {
        double d;
        Double boxed;
        List<Double> list;
    }

    @Test // 1
    void loadYamlConfigurationDoublesAllDecimal() {
        writeStringToFile("d: 10.0\nboxed: 20.0\nlist:\n  - 1.0\n  - 2.0\n  - 3.0\n");
        DoublesConfig config = YamlConfigurations.load(yamlFile, DoublesConfig.class);
        assertEquals(10.0, config.d);
        assertEquals(20.0, config.boxed);
        assertEquals(List.of(1.0, 2.0, 3.0), config.list); // PASSES
    }

    @Test // 2
    void loadYamlConfigurationDoublesUnboxed() {
        writeStringToFile("d: 10");
        DoublesConfig config = YamlConfigurations.load(yamlFile, DoublesConfig.class);
        assertEquals(10.0, config.d); // PASSES
    }

    @Test // 3
    void loadYamlConfigurationDoublesBoxed() {
        writeStringToFile("boxed: 20");
        DoublesConfig config = YamlConfigurations.load(yamlFile, DoublesConfig.class); // FAILS HERE
        assertEquals(20.0, config.boxed);
    }

    @Test // 4
    void loadYamlConfigurationDoublesCollection() {
        writeStringToFile("list:\n  - 1.0\n  - 2\n  - 3.0\n"); // 2.0 -> 2
        DoublesConfig config = YamlConfigurations.load(yamlFile, DoublesConfig.class);
        assertEquals(List.of(1.0, 2.0, 3.0), config.list); // FAILS HERE
    }

In test 2, ConfigLib correctly converts a double without a decimal point 10 to 10.0 to store in a primitive double field. This is the behavior I expect.

In test 3, the test fails in the load method:

Can not set java.lang.Double field de.exlll.configlib.YamlConfigurationsTest$DoublesConfig.boxed to java.lang.Long
java.lang.IllegalArgumentException: Can not set java.lang.Double field de.exlll.configlib.YamlConfigurationsTest$DoublesConfig.boxed to java.lang.Long

In test 4, the load method succeeds. However, the objects in the returned List are not all Doubles:

Expected :[1.0, 2.0, 3.0]
Actual   :[1.0, 2, 3.0]
<Click to see difference>

org.opentest4j.AssertionFailedError: expected: <[1.0, 2.0, 3.0]> but was: <[1.0, 2, 3.0]>

Expected behavior
Ideally, all of these cases would be handled like the primitive double, converting an integer type to a double when the receiving Configuration type calls for it. The case with the List was how I found this, and it was the most surprising since the exception is deferred until trying to unbox the double.

Screenshots
N/A

Additional context
I found this while using the update function, not directly read/load. After calling update, the contents of the yaml file are modified to contain a decimal point (e.g. - 2 becomes - 2.0). I think serialization is handling this correctly, but not deserialization.

Something similar may happen with other polymorphic types, but this is the simplest example.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions