Skip to content

Commit

Permalink
Fix #3056
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Feb 15, 2021
1 parent 1eb2c07 commit eba7b84
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 14 deletions.
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Project: jackson-databind
(fix contributed by Migwel@github)
#3038: Two cases of incorrect error reporting about DeserializationFeature
(reported by Jelle V)
#3056: MismatchedInputException: Cannot deserialize instance of
`com.fasterxml.jackson.databind.node.ObjectNode` out of VALUE_NULL token
(reported by Stexxen@github)

2.12.1 (08-Jan-2021)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,18 +389,25 @@ protected final JsonNode updateObject(JsonParser p, DeserializationContext ctxt,
JsonNode old = node.get(key);
if (old != null) {
if (old instanceof ObjectNode) {
JsonNode newValue = updateObject(p, ctxt, (ObjectNode) old);
if (newValue != old) {
node.set(key, newValue);
// [databind#3056]: merging only if had Object and
// getting an Object
if (t == JsonToken.START_OBJECT) {
JsonNode newValue = updateObject(p, ctxt, (ObjectNode) old);
if (newValue != old) {
node.set(key, newValue);
}
continue;
}
continue;
}
if (old instanceof ArrayNode) {
JsonNode newValue = updateArray(p, ctxt, (ArrayNode) old);
if (newValue != old) {
node.set(key, newValue);
} else if (old instanceof ArrayNode) {
// [databind#3056]: related to Object handling, ensure
// Array values also match for mergeability
if (t == JsonToken.START_ARRAY) {
JsonNode newValue = updateArray(p, ctxt, (ArrayNode) old);
if (newValue != old) {
node.set(key, newValue);
}
continue;
}
continue;
}
}
if (t == null) { // can this ever occur?
Expand Down Expand Up @@ -436,10 +443,15 @@ protected final JsonNode updateObject(JsonParser p, DeserializationContext ctxt,
default:
value = deserializeAny(p, ctxt, nodeFactory);
}
// 15-Feb-2021, tatu: I don't think this should have been called
// on update case (was until 2.12.2) and was simply result of
// copy-paste.
/*
if (old != null) {
_handleDuplicateField(p, ctxt, nodeFactory,
key, node, old, value);
}
*/
node.set(key, value);
}
return node;
Expand All @@ -449,8 +461,9 @@ protected final ArrayNode deserializeArray(JsonParser p, DeserializationContext
final JsonNodeFactory nodeFactory) throws IOException
{
ArrayNode node = nodeFactory.arrayNode();
while (true) {
JsonToken t = p.nextToken();
JsonToken t;

while ((t = p.nextToken()) != null) {
switch (t.id()) {
case JsonTokenId.ID_START_OBJECT:
node.add(deserializeObject(p, ctxt, nodeFactory));
Expand Down Expand Up @@ -483,6 +496,8 @@ protected final ArrayNode deserializeArray(JsonParser p, DeserializationContext
break;
}
}
// should never really get here
return node;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public class NodeMergeTest extends BaseMapTest
final static ObjectMapper MAPPER = jsonMapperBuilder()
// 26-Oct-2016, tatu: Make sure we'll report merge problems by default
.disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
// 15-Feb-2021, tatu: slightly related to [databind#3056],
// ensure that dup detection will not trip handling here
.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)
.build();

static class ObjectNodeWrapper {
Expand Down Expand Up @@ -69,8 +72,8 @@ public void testObjectDeepUpdate() throws Exception
base.putNull("misc");
assertSame(base,
MAPPER.readerForUpdating(base)
.readValue(aposToQuotes(
"{'props':{'value':true, 'extra':25.5, 'array' : [ 3 ]}}")));
.readValue(a2q(
"{'props':{'value':true, 'extra':25.5, 'array' : [ 3 ]}}")));
assertEquals(2, base.size());
ObjectNode resultProps = (ObjectNode) base.get("props");
assertEquals(4, resultProps.size());
Expand Down Expand Up @@ -114,4 +117,49 @@ public void testArrayNodeMerge() throws Exception
assertEquals(0, n.size());
assertEquals("foo", w.list.get(5).asText());
}

// [databind#3056]
public void testUpdateObjectNodeWithNull() throws Exception
{
JsonNode src = MAPPER.readTree(a2q("{'test':{}}"));
JsonNode update = MAPPER.readTree(a2q("{'test':null}"));

ObjectNode result = MAPPER.readerForUpdating(src)
.readValue(update, ObjectNode.class);

assertEquals(a2q("{'test':null}"), result.toString());
}

public void testUpdateObjectNodeWithNumber() throws Exception
{
JsonNode src = MAPPER.readTree(a2q("{'test':{}}"));
JsonNode update = MAPPER.readTree(a2q("{'test':123}"));

ObjectNode result = MAPPER.readerForUpdating(src)
.readValue(update, ObjectNode.class);

assertEquals(a2q("{'test':123}"), result.toString());
}

public void testUpdateArrayWithNull() throws Exception
{
JsonNode src = MAPPER.readTree(a2q("{'test':[]}"));
JsonNode update = MAPPER.readTree(a2q("{'test':null}"));

ObjectNode result = MAPPER.readerForUpdating(src)
.readValue(update, ObjectNode.class);

assertEquals(a2q("{'test':null}"), result.toString());
}

public void testUpdateArrayWithString() throws Exception
{
JsonNode src = MAPPER.readTree(a2q("{'test':[]}"));
JsonNode update = MAPPER.readTree(a2q("{'test':'n/a'}"));

ObjectNode result = MAPPER.readerForUpdating(src)
.readValue(update, ObjectNode.class);

assertEquals(a2q("{'test':'n/a'}"), result.toString());
}
}

0 comments on commit eba7b84

Please sign in to comment.