• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.convert;
2 
3 import java.math.BigInteger;
4 
5 import com.fasterxml.jackson.databind.*;
6 import com.fasterxml.jackson.databind.cfg.CoercionAction;
7 import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
8 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
9 import com.fasterxml.jackson.databind.type.LogicalType;
10 
11 public class CoerceFloatToIntTest extends BaseMapTest
12 {
13     private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
14     private final ObjectReader READER_LEGACY_FAIL = DEFAULT_MAPPER.reader()
15             .without(DeserializationFeature.ACCEPT_FLOAT_AS_INT);
16 
17     private final ObjectMapper MAPPER_TO_EMPTY; {
18         MAPPER_TO_EMPTY = newJsonMapper();
19         MAPPER_TO_EMPTY.coercionConfigFor(LogicalType.Integer)
20             .setCoercion(CoercionInputShape.Float, CoercionAction.AsEmpty);
21     }
22 
23     private final ObjectMapper MAPPER_TRY_CONVERT; {
24         MAPPER_TRY_CONVERT = newJsonMapper();
25         MAPPER_TRY_CONVERT.coercionConfigFor(LogicalType.Integer)
26             .setCoercion(CoercionInputShape.Float, CoercionAction.TryConvert);
27     }
28 
29     private final ObjectMapper MAPPER_TO_NULL; {
30         MAPPER_TO_NULL = newJsonMapper();
31         MAPPER_TO_NULL.coercionConfigFor(LogicalType.Integer)
32             .setCoercion(CoercionInputShape.Float, CoercionAction.AsNull);
33     }
34 
35     private final ObjectMapper MAPPER_TO_FAIL; {
36         MAPPER_TO_FAIL = newJsonMapper();
37         MAPPER_TO_FAIL.coercionConfigFor(LogicalType.Integer)
38             .setCoercion(CoercionInputShape.Float, CoercionAction.Fail);
39     }
40 
41     /*
42     /********************************************************
43     /* Test methods, defaults (legacy)
44     /********************************************************
45      */
46 
testLegacyDoubleToIntCoercion()47     public void testLegacyDoubleToIntCoercion() throws Exception
48     {
49         // by default, should be ok
50         Integer I = DEFAULT_MAPPER.readValue(" 1.25 ", Integer.class);
51         assertEquals(1, I.intValue());
52         {
53             IntWrapper w = DEFAULT_MAPPER.readValue("{\"i\":-2.25 }", IntWrapper.class);
54             assertEquals(-2, w.i);
55             int[] arr = DEFAULT_MAPPER.readValue("[ 1.25 ]", int[].class);
56             assertEquals(1, arr[0]);
57         }
58 
59         Long L = DEFAULT_MAPPER.readValue(" 3.33 ", Long.class);
60         assertEquals(3L, L.longValue());
61         {
62             LongWrapper w = DEFAULT_MAPPER.readValue("{\"l\":-2.25 }", LongWrapper.class);
63             assertEquals(-2L, w.l);
64             long[] arr = DEFAULT_MAPPER.readValue("[ 1.25 ]", long[].class);
65             assertEquals(1, arr[0]);
66         }
67 
68         Short S = DEFAULT_MAPPER.readValue("42.33", Short.class);
69         assertEquals(42, S.intValue());
70 
71         BigInteger biggie = DEFAULT_MAPPER.readValue("95.3", BigInteger.class);
72         assertEquals(95L, biggie.longValue());
73     }
74 
testLegacyFailDoubleToInt()75     public void testLegacyFailDoubleToInt() throws Exception
76     {
77         _verifyCoerceFail(READER_LEGACY_FAIL, Integer.class, "1.5", "java.lang.Integer");
78         _verifyCoerceFail(READER_LEGACY_FAIL, Integer.TYPE, "1.5", "int");
79         _verifyCoerceFail(READER_LEGACY_FAIL, IntWrapper.class, "{\"i\":-2.25 }", "int");
80         _verifyCoerceFail(READER_LEGACY_FAIL, int[].class, "[ 2.5 ]", "element of `int[]`");
81     }
82 
testLegacyFailDoubleToLong()83     public void testLegacyFailDoubleToLong() throws Exception
84     {
85         _verifyCoerceFail(READER_LEGACY_FAIL, Long.class, "0.5");
86         _verifyCoerceFail(READER_LEGACY_FAIL, Long.TYPE, "-2.5");
87         _verifyCoerceFail(READER_LEGACY_FAIL, LongWrapper.class, "{\"l\": 7.7 }");
88         _verifyCoerceFail(READER_LEGACY_FAIL, long[].class, "[ -1.35 ]", "element of `long[]`");
89     }
90 
testLegacyFailDoubleToOther()91     public void testLegacyFailDoubleToOther() throws Exception
92     {
93         _verifyCoerceFail(READER_LEGACY_FAIL, Short.class, "0.5");
94         _verifyCoerceFail(READER_LEGACY_FAIL, Short.TYPE, "-2.5");
95         _verifyCoerceFail(READER_LEGACY_FAIL, short[].class, "[ -1.35 ]", "element of `short[]`");
96 
97         _verifyCoerceFail(READER_LEGACY_FAIL, Byte.class, "0.5");
98         _verifyCoerceFail(READER_LEGACY_FAIL, Byte.TYPE, "-2.5");
99         _verifyCoerceFail(READER_LEGACY_FAIL, byte[].class, "[ -1.35 ]", "element of `byte[]`");
100 
101         _verifyCoerceFail(READER_LEGACY_FAIL, BigInteger.class, "25236.256");
102 
103         // 13-Jun-2020, tatu: No explicit deserializer for `AtomicLong` yet
104 //        _verifyCoerceFail(READER_LEGACY_FAIL, AtomicLong.class, "25236.256");
105     }
106 
107     /*
108     /********************************************************
109     /* Test methods, CoerceConfig, to null
110     /********************************************************
111      */
112 
testCoerceConfigFloatToNull()113     public void testCoerceConfigFloatToNull() throws Exception
114     {
115         assertNull(MAPPER_TO_NULL.readValue("1.5", Integer.class));
116         // `null` not possible for primitives, must use empty (aka default) value
117         assertEquals(Integer.valueOf(0), MAPPER_TO_NULL.readValue("1.5", Integer.TYPE));
118         {
119             IntWrapper w = MAPPER_TO_NULL.readValue( "{\"i\":-2.25 }", IntWrapper.class);
120             assertEquals(0, w.i);
121             int[] ints = MAPPER_TO_NULL.readValue("[ 2.5 ]", int[].class);
122             assertEquals(1, ints.length);
123             assertEquals(0, ints[0]);
124         }
125 
126         assertNull(MAPPER_TO_NULL.readValue("2.5", Long.class));
127         assertEquals(Long.valueOf(0L), MAPPER_TO_NULL.readValue("-4.25", Long.TYPE));
128         {
129             LongWrapper w = MAPPER_TO_NULL.readValue( "{\"l\":-2.25 }", LongWrapper.class);
130             assertEquals(0L, w.l);
131             long[] l = MAPPER_TO_NULL.readValue("[ 2.5 ]", long[].class);
132             assertEquals(1, l.length);
133             assertEquals(0L, l[0]);
134         }
135 
136         assertNull(MAPPER_TO_NULL.readValue("2.5", Short.class));
137         assertEquals(Short.valueOf((short) 0), MAPPER_TO_NULL.readValue("-4.25", Short.TYPE));
138         {
139             short[] s = MAPPER_TO_NULL.readValue("[ 2.5 ]", short[].class);
140             assertEquals(1, s.length);
141             assertEquals((short) 0, s[0]);
142         }
143 
144         assertNull(MAPPER_TO_NULL.readValue("2.5", Byte.class));
145         assertEquals(Byte.valueOf((byte) 0), MAPPER_TO_NULL.readValue("-4.25", Byte.TYPE));
146         {
147             byte[] arr = MAPPER_TO_NULL.readValue("[ 2.5 ]", byte[].class);
148             assertEquals(1, arr.length);
149             assertEquals((byte) 0, arr[0]);
150         }
151 
152         assertNull(MAPPER_TO_NULL.readValue("2.5", BigInteger.class));
153         {
154             BigInteger[] arr = MAPPER_TO_NULL.readValue("[ 2.5 ]", BigInteger[].class);
155             assertEquals(1, arr.length);
156             assertNull(arr[0]);
157         }
158     }
159 
160     /*
161     /********************************************************
162     /* Test methods, CoerceConfig, to empty
163     /********************************************************
164      */
165 
testCoerceConfigFloatToEmpty()166     public void testCoerceConfigFloatToEmpty() throws Exception
167     {
168         assertEquals(Integer.valueOf(0), MAPPER_TO_EMPTY.readValue("1.2", Integer.class));
169         assertEquals(Integer.valueOf(0), MAPPER_TO_EMPTY.readValue("1.5", Integer.TYPE));
170         {
171             IntWrapper w = MAPPER_TO_EMPTY.readValue( "{\"i\":-2.25 }", IntWrapper.class);
172             assertEquals(0, w.i);
173             int[] ints = MAPPER_TO_EMPTY.readValue("[ 2.5 ]", int[].class);
174             assertEquals(1, ints.length);
175             assertEquals(0, ints[0]);
176         }
177 
178         assertEquals(Long.valueOf(0), MAPPER_TO_EMPTY.readValue("1.2", Long.class));
179         assertEquals(Long.valueOf(0), MAPPER_TO_EMPTY.readValue("1.5", Long.TYPE));
180         {
181             LongWrapper w = MAPPER_TO_EMPTY.readValue( "{\"l\":-2.25 }", LongWrapper.class);
182             assertEquals(0L, w.l);
183             long[] l = MAPPER_TO_EMPTY.readValue("[ 2.5 ]", long[].class);
184             assertEquals(1, l.length);
185             assertEquals(0L, l[0]);
186         }
187 
188         assertEquals(Short.valueOf((short)0), MAPPER_TO_EMPTY.readValue("1.2", Short.class));
189         assertEquals(Short.valueOf((short) 0), MAPPER_TO_EMPTY.readValue("1.5", Short.TYPE));
190 
191         assertEquals(Byte.valueOf((byte)0), MAPPER_TO_EMPTY.readValue("1.2", Byte.class));
192         assertEquals(Byte.valueOf((byte) 0), MAPPER_TO_EMPTY.readValue("1.5", Byte.TYPE));
193 
194         assertEquals(BigInteger.valueOf(0L), MAPPER_TO_EMPTY.readValue("124.5", BigInteger.class));
195     }
196 
197     /*
198     /********************************************************
199     /* Test methods, CoerceConfig, coerce
200     /********************************************************
201      */
202 
testCoerceConfigFloatSuccess()203     public void testCoerceConfigFloatSuccess() throws Exception
204     {
205         assertEquals(Integer.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.2", Integer.class));
206         assertEquals(Integer.valueOf(3), MAPPER_TRY_CONVERT.readValue("3.4", Integer.TYPE));
207         {
208             IntWrapper w = MAPPER_TRY_CONVERT.readValue( "{\"i\":-2.25 }", IntWrapper.class);
209             assertEquals(-2, w.i);
210             int[] ints = MAPPER_TRY_CONVERT.readValue("[ 22.10 ]", int[].class);
211             assertEquals(1, ints.length);
212             assertEquals(22, ints[0]);
213         }
214 
215         assertEquals(Long.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.2", Long.class));
216         assertEquals(Long.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.5", Long.TYPE));
217         {
218             LongWrapper w = MAPPER_TRY_CONVERT.readValue( "{\"l\":-2.25 }", LongWrapper.class);
219             assertEquals(-2L, w.l);
220             long[] l = MAPPER_TRY_CONVERT.readValue("[ 2.2 ]", long[].class);
221             assertEquals(1, l.length);
222             assertEquals(2L, l[0]);
223         }
224 
225         assertEquals(Short.valueOf((short)1), MAPPER_TRY_CONVERT.readValue("1.2", Short.class));
226         assertEquals(Short.valueOf((short) 19), MAPPER_TRY_CONVERT.readValue("19.2", Short.TYPE));
227 
228         assertEquals(Byte.valueOf((byte)1), MAPPER_TRY_CONVERT.readValue("1.2", Byte.class));
229         assertEquals(Byte.valueOf((byte) 1), MAPPER_TRY_CONVERT.readValue("1.5", Byte.TYPE));
230 
231         assertEquals(BigInteger.valueOf(124L), MAPPER_TRY_CONVERT.readValue("124.2", BigInteger.class));
232     }
233 
234     /*
235     /********************************************************
236     /* Test methods, CoerceConfig, fail
237     /********************************************************
238      */
239 
testCoerceConfigFailFromFloat()240     public void testCoerceConfigFailFromFloat() throws Exception
241     {
242         _verifyCoerceFail(MAPPER_TO_FAIL, Integer.class, "1.5");
243         _verifyCoerceFail(MAPPER_TO_FAIL, Integer.TYPE, "1.5");
244         _verifyCoerceFail(MAPPER_TO_FAIL, IntWrapper.class, "{\"i\":-2.25 }", "int");
245         _verifyCoerceFail(MAPPER_TO_FAIL, int[].class, "[ 2.5 ]", "element of `int[]`");
246 
247         _verifyCoerceFail(MAPPER_TO_FAIL, Long.class, "0.5");
248         _verifyCoerceFail(MAPPER_TO_FAIL, Long.TYPE, "-2.5");
249         _verifyCoerceFail(MAPPER_TO_FAIL, LongWrapper.class, "{\"l\": 7.7 }");
250         _verifyCoerceFail(MAPPER_TO_FAIL, long[].class, "[ -1.35 ]", "element of `long[]`");
251 
252         _verifyCoerceFail(MAPPER_TO_FAIL, Short.class, "0.5");
253         _verifyCoerceFail(MAPPER_TO_FAIL, Short.TYPE, "-2.5");
254         _verifyCoerceFail(MAPPER_TO_FAIL, short[].class, "[ -1.35 ]", "element of `short[]`");
255 
256         _verifyCoerceFail(MAPPER_TO_FAIL, Byte.class, "0.5");
257         _verifyCoerceFail(MAPPER_TO_FAIL, Byte.TYPE, "-2.5");
258         _verifyCoerceFail(MAPPER_TO_FAIL, byte[].class, "[ -1.35 ]", "element of `byte[]`");
259 
260         _verifyCoerceFail(MAPPER_TO_FAIL, BigInteger.class, "25236.256");
261     }
262 
263     /*
264     /********************************************************
265     /* Helper methods
266     /********************************************************
267      */
268 
_verifyCoerceFail(ObjectMapper m, Class<?> targetType, String doc)269     private void _verifyCoerceFail(ObjectMapper m, Class<?> targetType,
270             String doc) throws Exception
271     {
272         _verifyCoerceFail(m.reader(), targetType, doc, targetType.getName());
273     }
274 
_verifyCoerceFail(ObjectMapper m, Class<?> targetType, String doc, String targetTypeDesc)275     private void _verifyCoerceFail(ObjectMapper m, Class<?> targetType,
276             String doc, String targetTypeDesc) throws Exception
277     {
278         _verifyCoerceFail(m.reader(), targetType, doc, targetTypeDesc);
279     }
280 
_verifyCoerceFail(ObjectReader r, Class<?> targetType, String doc)281     private void _verifyCoerceFail(ObjectReader r, Class<?> targetType,
282             String doc) throws Exception
283     {
284         _verifyCoerceFail(r, targetType, doc, targetType.getName());
285     }
286 
_verifyCoerceFail(ObjectReader r, Class<?> targetType, String doc, String targetTypeDesc)287     private void _verifyCoerceFail(ObjectReader r, Class<?> targetType,
288             String doc, String targetTypeDesc) throws Exception
289     {
290         try {
291             r.forType(targetType).readValue(doc);
292             fail("Should not accept Float for "+targetType.getName()+" by default");
293         } catch (MismatchedInputException e) {
294             verifyException(e, "Cannot coerce Floating-point");
295             verifyException(e, targetTypeDesc);
296         }
297     }
298 }
299