Skip to content

Commit

Permalink
Fix #989
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Oct 29, 2015
1 parent fe25f7e commit d5a25f4
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
4 changes: 4 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,7 @@ Jesse Wilson (swankjesse@github)
Warren Bloomer (stormboy@github)
* Reported #942: Handle null type id for polymorphic values that use external type id
(2.6.3)

Ievgen Pianov (pyanoveugen@github)
* Reported #989: Deserialization from "{}" to java.lang.Object causes "out of END_OBJECT token" error
(2.6.3)
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Project: jackson-databind

#984: JsonStreamContexts are not build the same way for write.. and convert methods
(reported by Antibrumm@github)
#989: Deserialization from "{}" to java.lang.Object causes "out of END_OBJECT token" error
(reported by Ievgen P)

2.6.3 (12-Oct-2015)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
switch (p.getCurrentTokenId()) {
case JsonTokenId.ID_START_OBJECT:
case JsonTokenId.ID_FIELD_NAME:
// 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
// if caller has advanced to the first token of Object, but for empty Object
case JsonTokenId.ID_END_OBJECT:
if (_mapDeserializer != null) {
return _mapDeserializer.deserialize(p, ctxt);
}
Expand Down Expand Up @@ -269,7 +272,6 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
return null;

// case JsonTokenId.ID_END_ARRAY: // invalid
// case JsonTokenId.ID_END_OBJECT: // invalid
default:
}
throw ctxt.mappingException(Object.class);
Expand Down Expand Up @@ -314,7 +316,6 @@ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, Typ
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
// For [JACKSON-72], see above
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return p.getDecimalValue();
}
Expand Down Expand Up @@ -400,12 +401,11 @@ protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOE
}
key1 = null;
}

// minor optimization; let's handle 1 and 2 entry cases separately
if (key1 == null) {
// empty map might work; but caller may want to modify... so better just give small modifiable
return new LinkedHashMap<String,Object>(2);
}
// minor optimization; let's handle 1 and 2 entry cases separately
// 24-Mar-2015, tatu: Ideally, could use one of 'nextXxx()' methods, but for
// that we'd need new method(s) in JsonDeserializer. So not quite yet.
p.nextToken();
Expand Down Expand Up @@ -488,7 +488,7 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
case JsonTokenId.ID_START_OBJECT:
{
JsonToken t = p.nextToken();
if (t == JsonToken.END_OBJECT) {
if (t == JsonToken.END_OBJECT) {
return new LinkedHashMap<String,Object>(2);
}
}
Expand Down Expand Up @@ -533,8 +533,12 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
case JsonTokenId.ID_NULL: // should not get this but...
return null;

case JsonTokenId.ID_END_OBJECT:
// 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
// if caller has advanced to the first token of Object, but for empty Object
return new LinkedHashMap<String,Object>(2);

//case JsonTokenId.ID_END_ARRAY: // invalid
//case JsonTokenId.ID_END_OBJECT: // invalid
default:
throw ctxt.mappingException(Object.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.*;
import java.util.*;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
Expand Down Expand Up @@ -90,12 +91,23 @@ public Map<String,Object> deserialize(JsonParser jp, DeserializationContext ctxt
return map;
}
}

static class Untyped989 {
protected Object value;

@JsonCreator // delegating
public Untyped989(Object v) {
value = v;
}
}

/*
/**********************************************************
/* Test methods
/**********************************************************
*/

private final ObjectMapper MAPPER = new ObjectMapper();

@SuppressWarnings("unchecked")
public void testSampleDoc() throws Exception
Expand All @@ -105,7 +117,7 @@ public void testSampleDoc() throws Exception
/* To get "untyped" Mapping (to Maps, Lists, instead of beans etc),
* we'll specify plain old Object.class as the target.
*/
Object root = new ObjectMapper().readValue(JSON, Object.class);
Object root = MAPPER.readValue(JSON, Object.class);

assertType(root, Map.class);
Map<?,?> rootMap = (Map<?,?>) root;
Expand Down Expand Up @@ -154,8 +166,7 @@ public void testSampleDoc() throws Exception
public void testNestedUntypes() throws IOException
{
// 05-Apr-2014, tatu: Odd failures if using shared mapper; so work around:
final ObjectMapper mapper = new ObjectMapper();
Object root = mapper.readValue(aposToQuotes("{'a':3,'b':[1,2]}"),
Object root = MAPPER.readValue(aposToQuotes("{'a':3,'b':[1,2]}"),
Object.class);
assertTrue(root instanceof Map<?,?>);
Map<?,?> map = (Map<?,?>) root;
Expand All @@ -168,7 +179,7 @@ public void testNestedUntypes() throws IOException
assertEquals(Integer.valueOf(2), l.get(1));
}

// [JACKSON-839]: allow 'upgrade' of big integers into Long, BigInteger
// Allow 'upgrade' of big integers into Long, BigInteger
public void testObjectSerializeWithLong() throws IOException
{
final ObjectMapper mapper = new ObjectMapper();
Expand Down Expand Up @@ -239,4 +250,20 @@ public void testUntypedWithMapDeser() throws IOException
assertEquals(1, map.size());
assertEquals("Ytrue", map.get("a"));
}

public void testNestedUntyped989() throws IOException
{
Untyped989 pojo;
ObjectReader r = MAPPER.readerFor(Untyped989.class);

pojo = r.readValue("[]");
assertTrue(pojo.value instanceof List);
pojo = r.readValue("[{}]");
assertTrue(pojo.value instanceof List);

pojo = r.readValue("{}");
assertTrue(pojo.value instanceof Map);
pojo = r.readValue("{\"a\":[]}");
assertTrue(pojo.value instanceof Map);
}
}

0 comments on commit d5a25f4

Please sign in to comment.