Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
Fix #16
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jan 23, 2016
1 parent 9045c59 commit f85c708
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 18 deletions.
6 changes: 6 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Project: jackson-datatype-jsr310
=== Releases ===
------------------------------------------------------------------------

2.6.6 (not released yet)

#16: Instant is serialized as String by some dataformats/libs but can't be
deserialized (unless manually converted to float)
(reported by Andreas L)

2.6.5 (19-Jan-2016)

No changes since 2.6.4.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,33 +119,32 @@ public T deserialize(JsonParser parser, DeserializationContext context) throws I
switch (parser.getCurrentTokenId())
{
case JsonTokenId.ID_NUMBER_FLOAT:
{
BigDecimal value = parser.getDecimalValue();
long seconds = value.longValue();
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds);
return fromNanoseconds.apply(new FromDecimalArguments(
seconds, nanoseconds, getZone(context)));
}
return _fromDecimal(context, parser.getDecimalValue());

case JsonTokenId.ID_NUMBER_INT:
{
long timestamp = parser.getLongValue();
if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)){
return this.fromNanoseconds.apply(new FromDecimalArguments(
timestamp, 0, this.getZone(context)
));
}
return this.fromMilliseconds.apply(new FromIntegerArguments(
timestamp, this.getZone(context)
));
}
return _fromLong(context, parser.getLongValue());

case JsonTokenId.ID_STRING:
{
String string = parser.getText().trim();
if (string.length() == 0) {
return null;
}
// 22-Jan-2016, [datatype-jsr310#16]: Allow quoted numbers too
int dots = _countPeriods(string);
if (dots >= 0) { // negative if not simple number
try {
if (dots == 0) {
return _fromLong(context, Long.parseLong(string));
}
if (dots == 1) {
return _fromDecimal(context, new BigDecimal(string));
}
} catch (NumberFormatException e) {
// fall through to default handling, to get error there
}
}

T value;
try {
TemporalAccessor acc = _formatter.parse(string);
Expand All @@ -161,6 +160,44 @@ public T deserialize(JsonParser parser, DeserializationContext context) throws I
}
throw context.mappingException("Expected type float, integer, or string.");
}

/**
* Helper method to find Strings of form "all digits" and "digits-comma-digits"
*/
protected int _countPeriods(String str)
{
int commas = 0;
for (int i = 0, end = str.length(); i < end; ++i) {
int ch = str.charAt(i);
if (ch < '0' || ch > '9') {
if (ch == '.') {
++commas;
} else {
return -1;
}
}
}
return commas;
}

protected T _fromLong(DeserializationContext context, long timestamp)
{
if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)){
return fromNanoseconds.apply(new FromDecimalArguments(
timestamp, 0, this.getZone(context)
));
}
return fromMilliseconds.apply(new FromIntegerArguments(
timestamp, this.getZone(context)));
}

protected T _fromDecimal(DeserializationContext context, BigDecimal value)
{
long seconds = value.longValue();
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds);
return fromNanoseconds.apply(new FromDecimalArguments(
seconds, nanoseconds, getZone(context)));
}

private ZoneId getZone(DeserializationContext context)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,25 @@ public void testCustomPatternWithAnnotations() throws Exception
Wrapper result = mapper.readValue(json, Wrapper.class);
assertEquals(input.value, result.value);
}

// [datatype-jsr310#16]
@Test
public void testDeserializationFromStringAsNumber() throws Exception
{
// First, baseline test with floating-point numbers
Instant inst = Instant.now();
String json = mapper.writer()
.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.with(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
.writeValueAsString(inst);
Instant result = mapper.readValue(json, Instant.class);
assertNotNull(result);
assertEquals(result, inst);

// but then quoted as JSON String
result = mapper.readValue(String.format("\"%s\"", json),
Instant.class);
assertNotNull(result);
assertEquals(result, inst);
}
}

0 comments on commit f85c708

Please sign in to comment.