Skip to content

Commit 4d4d141

Browse files
authored
Fix #490: regression in Double/Float conversion for "untyped" deserialization (#492)
1 parent 1efa12b commit 4d4d141

File tree

4 files changed

+75
-3
lines changed

4 files changed

+75
-3
lines changed

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonParser.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ private double _getDoubleValue() throws IOException {
369369
@Override
370370
public float getFloatValue() throws IOException {
371371
_verifyIsNumberToken();
372+
// 04-May-2024, tatu: May seem odd but Ion really does not
373+
// expose 32-bit floats even if it MAY use them internally
374+
// for encoding. So:
372375
return (float) _getDoubleValue();
373376
}
374377

@@ -472,6 +475,7 @@ public NumberType getNumberType() throws IOException
472475
return NumberType.BIG_INTEGER;
473476
}
474477
case FLOAT:
478+
// 04-May-2024, tatu: Ion really does not expose 32-bit floats, so:
475479
return NumberType.DOUBLE;
476480
default:
477481
}
@@ -489,7 +493,9 @@ public NumberTypeFP getNumberTypeFP() throws IOException
489493
// 06-Jan-2024, tatu: Existing code maps Ion `FLOAT` into Java
490494
// `float`. But code in `IonReader` suggests `Double` might
491495
// be more accurate mapping... odd.
492-
return NumberTypeFP.FLOAT32;
496+
// 04-May-2024, tatu: Ion really does not expose 32-bit floats;
497+
// must expose as 64-bit here too
498+
return NumberTypeFP.DOUBLE64;
493499
}
494500
if (type == IonType.DECIMAL) {
495501
// 06-Jan-2024, tatu: Seems like `DECIMAL` is expected to map
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.fasterxml.jackson.dataformat.ion;
2+
3+
import java.util.*;
4+
import org.junit.Test;
5+
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
8+
import static org.junit.Assert.*;
9+
10+
// for [dataformats-binary#490]
11+
public class DatabindNumberRoundtrip490Test
12+
{
13+
private final IonObjectMapper BINARY_MAPPER = IonObjectMapper.builderForBinaryWriters()
14+
.build();
15+
private final IonObjectMapper TEXT_MAPPER = IonObjectMapper.builderForTextualWriters()
16+
.build();
17+
18+
@Test
19+
public void testBinaryFloats() throws Exception {
20+
_floatRoundtrip(BINARY_MAPPER);
21+
}
22+
23+
@Test
24+
public void testBinaryIntegers() throws Exception {
25+
_integerRoundtrip490(BINARY_MAPPER);
26+
}
27+
28+
@Test
29+
public void testTextualFloats() throws Exception {
30+
_floatRoundtrip(TEXT_MAPPER);
31+
}
32+
33+
@Test
34+
public void testTextualIntegers() throws Exception {
35+
_integerRoundtrip490(TEXT_MAPPER);
36+
}
37+
38+
private void _floatRoundtrip(ObjectMapper mapper) throws Exception
39+
{
40+
final double d = 42.25d;
41+
final float f = 42.75f;
42+
43+
_roundtrip490(mapper, d, d);
44+
45+
// Ion oddity: "float"s get upgraded to "double"s, so...
46+
_roundtrip490(mapper, f, (double) f);
47+
}
48+
49+
private void _integerRoundtrip490(ObjectMapper mapper) throws Exception
50+
{
51+
_roundtrip490(mapper, Integer.MAX_VALUE, Integer.MAX_VALUE);
52+
_roundtrip490(mapper, Long.MAX_VALUE, Long.MAX_VALUE);
53+
}
54+
55+
private void _roundtrip490(ObjectMapper mapper,
56+
Object input, Object result)
57+
throws Exception
58+
{
59+
byte[] serialized = mapper.writeValueAsBytes(Collections.singletonMap("k", input));
60+
61+
Map<?,?> deserialized = mapper.readValue(serialized, Map.class);
62+
assertEquals(result, deserialized.get("k"));
63+
}
64+
}

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/IonParserTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ public void testGetNumberTypeAndValue() throws Exception {
7575
IonParser floatParser = new IonFactory().createParser(ionFloat);
7676
Assert.assertEquals(JsonToken.VALUE_NUMBER_FLOAT, floatParser.nextToken());
7777
Assert.assertEquals(JsonParser.NumberType.DOUBLE, floatParser.getNumberType());
78-
Assert.assertEquals(JsonParser.NumberTypeFP.FLOAT32, floatParser.getNumberTypeFP());
78+
// [dataformats-binary#490]: float coerces to double
79+
Assert.assertEquals(JsonParser.NumberTypeFP.DOUBLE64, floatParser.getNumberTypeFP());
7980
Assert.assertEquals(floatValue, floatParser.getNumberValue());
8081

8182
BigDecimal bigDecimalValue = new BigDecimal(Double.MAX_VALUE + "1");

release-notes/VERSION-2.x

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ Active maintainers:
2323
#487 (ion): Don't close IonParser on EOF to be compatible with `MappingIterator`
2424
when source is an empty `InputStream`
2525
(contributed by Yoann V)
26-
2726
#488 (ion): Upgrade `ion-java` to 1.11.7 (from 1.11.2)
27+
#490 (ion) ION deserialization type change from Double to Float in 2.17.0
28+
(reported by Florian H)
2829

2930
2.17.0 (12-Mar-2024)
3031

0 commit comments

Comments
 (0)