Skip to content

Commit 9317e54

Browse files
committed
Follow-up to #852, add unit test
1 parent b4547f8 commit 9317e54

File tree

4 files changed

+58
-23
lines changed

4 files changed

+58
-23
lines changed

release-notes/VERSION

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Project: jackson-databind
44
=== Releases ===
55
------------------------------------------------------------------------
66

7+
2.5.5 (not released)
8+
9+
#852: Accept scientific number notation for quoted numbers too
10+
711
2.5.4 (09-Jun-2015)
812

913
#676: Deserialization of class with generic collection inside depends on

src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ public Number deserialize(JsonParser jp, DeserializationContext ctxt)
439439
return Double.NaN;
440440
}
441441
try {
442-
if (text.indexOf('.') >= 0) { // floating point
442+
if (!_isIntNumber(text)) {
443443
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
444444
return new BigDecimal(text);
445445
}
@@ -501,7 +501,7 @@ public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
501501
/* types
502502
/**********************************************************
503503
*/
504-
504+
505505
/**
506506
* This is bit trickier to implement efficiently, while avoiding
507507
* overflow problems.

src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java

+22
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,28 @@ protected JsonDeserializer<Object> findDeserializer(DeserializationContext ctxt,
882882
return ctxt.findContextualValueDeserializer(type, property);
883883
}
884884

885+
/**
886+
* Helper method to check whether given text refers to what looks like a clean simple
887+
* integer number, consisting of optional sign followed by a sequence of digits.
888+
*/
889+
protected final boolean _isIntNumber(String text)
890+
{
891+
final int len = text.length();
892+
if (len > 0) {
893+
char c = text.charAt(0);
894+
// skip leading sign (plus not allowed for strict JSON numbers but...)
895+
int i = (c == '-' || c == '+') ? 1 : 0;
896+
for (; i < len; ++i) {
897+
int ch = text.charAt(i);
898+
if (ch > '9' || ch < '0') {
899+
return false;
900+
}
901+
}
902+
return true;
903+
}
904+
return false;
905+
}
906+
885907
/*
886908
/**********************************************************
887909
/* Helper methods for sub-classes, deserializer construction

src/test/java/com/fasterxml/jackson/databind/deser/TestNumbers.java

+30-21
Original file line numberDiff line numberDiff line change
@@ -57,70 +57,79 @@ public MyBeanValue deserialize(JsonParser jp, DeserializationContext ctxt)
5757
/* Unit tests
5858
/**********************************************************************
5959
*/
60+
61+
final ObjectMapper MAPPER = new ObjectMapper();
6062

6163
public void testNaN() throws Exception
6264
{
63-
ObjectMapper m = new ObjectMapper();
64-
Float result = m.readValue(" \"NaN\"", Float.class);
65+
Float result = MAPPER.readValue(" \"NaN\"", Float.class);
6566
assertEquals(Float.valueOf(Float.NaN), result);
6667

67-
Double d = m.readValue(" \"NaN\"", Double.class);
68+
Double d = MAPPER.readValue(" \"NaN\"", Double.class);
6869
assertEquals(Double.valueOf(Double.NaN), d);
6970

70-
Number num = m.readValue(" \"NaN\"", Number.class);
71+
Number num = MAPPER.readValue(" \"NaN\"", Number.class);
7172
assertEquals(Double.valueOf(Double.NaN), num);
7273
}
7374

7475
public void testDoubleInf() throws Exception
7576
{
76-
ObjectMapper m = new ObjectMapper();
77-
Double result = m.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class);
77+
Double result = MAPPER.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class);
7878
assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), result);
7979

80-
result = m.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class);
80+
result = MAPPER.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class);
8181
assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), result);
8282
}
8383

8484
// [JACKSON-349]
8585
public void testEmptyAsNumber() throws Exception
8686
{
87-
ObjectMapper m = new ObjectMapper();
88-
assertNull(m.readValue(quote(""), Integer.class));
89-
assertNull(m.readValue(quote(""), Long.class));
90-
assertNull(m.readValue(quote(""), Float.class));
91-
assertNull(m.readValue(quote(""), Double.class));
92-
assertNull(m.readValue(quote(""), BigInteger.class));
93-
assertNull(m.readValue(quote(""), BigDecimal.class));
87+
assertNull(MAPPER.readValue(quote(""), Integer.class));
88+
assertNull(MAPPER.readValue(quote(""), Long.class));
89+
assertNull(MAPPER.readValue(quote(""), Float.class));
90+
assertNull(MAPPER.readValue(quote(""), Double.class));
91+
assertNull(MAPPER.readValue(quote(""), BigInteger.class));
92+
assertNull(MAPPER.readValue(quote(""), BigDecimal.class));
9493
}
9594

9695
// // Tests for [JACKSON-668]
97-
96+
9897
public void testDeserializeDecimalHappyPath() throws Exception {
99-
ObjectMapper mapper = new ObjectMapper();
10098
String json = "{\"defaultValue\": { \"value\": 123 } }";
101-
MyBeanHolder result = mapper.readValue(json, MyBeanHolder.class);
99+
MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
102100
assertEquals(BigDecimal.valueOf(123), result.defaultValue.value.decimal);
103101
}
104102

105103
public void testDeserializeDecimalProperException() throws Exception {
106-
ObjectMapper mapper = new ObjectMapper();
107104
String json = "{\"defaultValue\": { \"value\": \"123\" } }";
108105
try {
109-
mapper.readValue(json, MyBeanHolder.class);
106+
MAPPER.readValue(json, MyBeanHolder.class);
110107
fail("should have raised exception");
111108
} catch (JsonProcessingException e) {
112109
verifyException(e, "not numeric");
113110
}
114111
}
115112

116113
public void testDeserializeDecimalProperExceptionWhenIdSet() throws Exception {
117-
ObjectMapper mapper = new ObjectMapper();
118114
String json = "{\"id\": 5, \"defaultValue\": { \"value\": \"123\" } }";
119115
try {
120-
MyBeanHolder result = mapper.readValue(json, MyBeanHolder.class);
116+
MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
121117
fail("should have raised exception instead value was set to " + result.defaultValue.value.decimal.toString());
122118
} catch (JsonProcessingException e) {
123119
verifyException(e, "not numeric");
124120
}
125121
}
122+
123+
// And then [databind#852]
124+
public void testScientificNotationForString() throws Exception
125+
{
126+
Object ob = MAPPER.readValue("\"3E-8\"", Number.class);
127+
assertEquals(Double.class, ob.getClass());
128+
ob = MAPPER.readValue("\"3e-8\"", Number.class);
129+
assertEquals(Double.class, ob.getClass());
130+
ob = MAPPER.readValue("\"300000000\"", Number.class);
131+
assertEquals(Integer.class, ob.getClass());
132+
ob = MAPPER.readValue("\"123456789012\"", Number.class);
133+
assertEquals(Long.class, ob.getClass());
134+
}
126135
}

0 commit comments

Comments
 (0)