aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/fasterxml/jackson
diff options
context:
space:
mode:
authorTatu Saloranta <tatu.saloranta@iki.fi>2020-07-01 17:40:42 -0700
committerTatu Saloranta <tatu.saloranta@iki.fi>2020-07-01 17:40:42 -0700
commit58c9211bcc04d3bd4e6e726f10997fc7e6538e25 (patch)
tree6e0ce086287cc3080b079d50e232c41e743a1f68 /src/main/java/com/fasterxml/jackson
parent3e5b76a69ce9324ccda7c53ddec52e818b207977 (diff)
downloadjackson-databind-58c9211bcc04d3bd4e6e726f10997fc7e6538e25.tar.gz
Refactoring to (eventually) allow XmlMapper override wrapped-root handling
Diffstat (limited to 'src/main/java/com/fasterxml/jackson')
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java64
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ObjectReader.java102
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java65
3 files changed, 81 insertions, 150 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index 899149f69..ab273ffc1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -4497,13 +4497,7 @@ public class ObjectMapper
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else { // pointing to event other than null
- JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
- // ok, let's get the value
- if (cfg.useRootWrapping()) {
- result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
- } else {
- result = deser.deserialize(p, ctxt);
- }
+ result = ctxt.readRootValue(p, valueType, _findRootDeserializer(ctxt, valueType), null);
}
// Need to consume the token too
p.clearCurrentToken();
@@ -4527,12 +4521,8 @@ public class ObjectMapper
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else {
- JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
- if (cfg.useRootWrapping()) {
- result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
- } else {
- result = deser.deserialize(p, ctxt);
- }
+ result = ctxt.readRootValue(p, valueType,
+ _findRootDeserializer(ctxt, valueType), null);
ctxt.checkUnresolvedObjectId();
}
if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
@@ -4573,57 +4563,19 @@ public class ObjectMapper
if (t == JsonToken.VALUE_NULL) {
resultNode = cfg.getNodeFactory().nullNode();
} else {
- JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
- if (cfg.useRootWrapping()) {
- resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
- } else {
- resultNode = (JsonNode) deser.deserialize(p, ctxt);
- }
+ resultNode = (JsonNode) ctxt.readRootValue(p, valueType,
+ _findRootDeserializer(ctxt, valueType), null);
+ // No ObjectIds so can ignore
+// ctxt.checkUnresolvedObjectId();
}
if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
_verifyNoTrailingTokens(p, ctxt, valueType);
}
- // No ObjectIds so can ignore
-// ctxt.checkUnresolvedObjectId();
return resultNode;
}
}
- protected Object _unwrapAndDeserialize(JsonParser p, DeserializationContext ctxt,
- DeserializationConfig config,
- JavaType rootType, JsonDeserializer<Object> deser)
- throws IOException
- {
- PropertyName expRootName = config.findRootName(rootType);
- // 12-Jun-2015, tatu: Should try to support namespaces etc but...
- String expSimpleName = expRootName.getSimpleName();
- if (p.currentToken() != JsonToken.START_OBJECT) {
- ctxt.reportWrongTokenException(rootType, JsonToken.START_OBJECT,
- "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- if (p.nextToken() != JsonToken.FIELD_NAME) {
- ctxt.reportWrongTokenException(rootType, JsonToken.FIELD_NAME,
- "Current token not FIELD_NAME (to contain expected root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- String actualName = p.getCurrentName();
- if (!expSimpleName.equals(actualName)) {
- ctxt.reportPropertyInputMismatch(rootType, actualName,
- "Root name '%s' does not match expected ('%s') for type %s",
- actualName, expSimpleName, rootType);
- }
- // ok, then move to value itself....
- p.nextToken();
- Object result = deser.deserialize(p, ctxt);
- // and last, verify that we now get matching END_OBJECT
- if (p.nextToken() != JsonToken.END_OBJECT) {
- ctxt.reportWrongTokenException(rootType, JsonToken.END_OBJECT,
- "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- return result;
- }
+
/**
* Internal helper method called to create an instance of {@link DeserializationContext}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
index 17ca4d65a..313f39276 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
@@ -2011,18 +2011,7 @@ public class ObjectReader
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = valueToUpdate;
} else { // pointing to event other than null
- JsonDeserializer<Object> deser = _findRootDeserializer(ctxt);
- if (_unwrapRoot) {
- result = _unwrapAndDeserialize(p, ctxt, _valueType, deser);
- } else {
- if (valueToUpdate == null) {
- result = deser.deserialize(p, ctxt);
- } else {
- // 20-Mar-2017, tatu: Important! May be different from `valueToUpdate`
- // for immutable Objects like Java arrays; logical result
- result = deser.deserialize(p, ctxt, valueToUpdate);
- }
- }
+ result = ctxt.readRootValue(p, _valueType, _findRootDeserializer(ctxt), _valueToUpdate);
}
// Need to consume the token too
p.clearCurrentToken();
@@ -2037,7 +2026,7 @@ public class ObjectReader
try (JsonParser p = p0) {
Object result;
- DefaultDeserializationContext ctxt = createDeserializationContext(p);
+ final DefaultDeserializationContext ctxt = createDeserializationContext(p);
JsonToken t = _initForReading(ctxt, p);
if (t == JsonToken.VALUE_NULL) {
if (_valueToUpdate == null) {
@@ -2048,17 +2037,7 @@ public class ObjectReader
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = _valueToUpdate;
} else {
- JsonDeserializer<Object> deser = _findRootDeserializer(ctxt);
- if (_unwrapRoot) {
- result = _unwrapAndDeserialize(p, ctxt, _valueType, deser);
- } else {
- if (_valueToUpdate == null) {
- result = deser.deserialize(p, ctxt);
- } else {
- deser.deserialize(p, ctxt, _valueToUpdate);
- result = _valueToUpdate;
- }
- }
+ result = ctxt.readRootValue(p, _valueType, _findRootDeserializer(ctxt), _valueToUpdate);
}
if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
_verifyNoTrailingTokens(p, ctxt, _valueType);
@@ -2088,24 +2067,14 @@ public class ObjectReader
return _config.getNodeFactory().missingNode();
}
}
- final DefaultDeserializationContext ctxt;
+ final DefaultDeserializationContext ctxt = createDeserializationContext(p);
final JsonNode resultNode;
- final boolean checkTrailing = _config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
if (t == JsonToken.VALUE_NULL) {
resultNode = _config.getNodeFactory().nullNode();
- if (!checkTrailing) {
- return resultNode;
- }
- ctxt = createDeserializationContext(p);
} else {
- ctxt = createDeserializationContext(p);
- final JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
- if (_unwrapRoot) {
- resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, _jsonNodeType(), deser);
- } else {
- resultNode = (JsonNode) deser.deserialize(p, ctxt);
- }
+ // Will not be called for merge (need not pass _valueToUpdate)
+ resultNode = (JsonNode) ctxt.readRootValue(p, _jsonNodeType(), _findTreeDeserializer(ctxt), null);
}
if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
_verifyNoTrailingTokens(p, ctxt, _jsonNodeType());
@@ -2130,25 +2099,15 @@ public class ObjectReader
return null;
}
}
- final DefaultDeserializationContext ctxt;
+ final DefaultDeserializationContext ctxt = createDeserializationContext(p);
final JsonNode resultNode;
- final boolean checkTrailing = _config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
if (t == JsonToken.VALUE_NULL) {
resultNode = _config.getNodeFactory().nullNode();
- if (!checkTrailing) {
- return resultNode;
- }
- ctxt = createDeserializationContext(p);
} else {
- ctxt = createDeserializationContext(p);
- final JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
- if (_unwrapRoot) {
- resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, _jsonNodeType(), deser);
- } else {
- resultNode = (JsonNode) deser.deserialize(p, ctxt);
- }
+ // Will not be called for merge (need not pass _valueToUpdate)
+ resultNode = (JsonNode) ctxt.readRootValue(p, _jsonNodeType(), _findTreeDeserializer(ctxt), null);
}
- if (checkTrailing) {
+ if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
_verifyNoTrailingTokens(p, ctxt, _jsonNodeType());
}
return resultNode;
@@ -2165,47 +2124,6 @@ public class ObjectReader
return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true);
}
- protected Object _unwrapAndDeserialize(JsonParser p, DeserializationContext ctxt,
- JavaType rootType, JsonDeserializer<Object> deser) throws IOException
- {
- PropertyName expRootName = _config.findRootName(rootType);
- // 12-Jun-2015, tatu: Should try to support namespaces etc but...
- String expSimpleName = expRootName.getSimpleName();
-
- if (p.currentToken() != JsonToken.START_OBJECT) {
- ctxt.reportWrongTokenException(rootType, JsonToken.START_OBJECT,
- "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- if (p.nextToken() != JsonToken.FIELD_NAME) {
- ctxt.reportWrongTokenException(rootType, JsonToken.FIELD_NAME,
- "Current token not FIELD_NAME (to contain expected root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- String actualName = p.getCurrentName();
- if (!expSimpleName.equals(actualName)) {
- ctxt.reportPropertyInputMismatch(rootType, actualName,
- "Root name '%s' does not match expected ('%s') for type %s",
- actualName, expSimpleName, rootType);
- }
- // ok, then move to value itself....
- p.nextToken();
- Object result;
- if (_valueToUpdate == null) {
- result = deser.deserialize(p, ctxt);
- } else {
- deser.deserialize(p, ctxt, _valueToUpdate);
- result = _valueToUpdate;
- }
- // and last, verify that we now get matching END_OBJECT
- if (p.nextToken() != JsonToken.END_OBJECT) {
- ctxt.reportWrongTokenException(rootType, JsonToken.END_OBJECT,
- "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s",
- expSimpleName, p.currentToken());
- }
- return result;
- }
-
/**
* Consider filter when creating JsonParser.
*/
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
index 8a66c307d..cf43d1f56 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
@@ -1,5 +1,6 @@
package com.fasterxml.jackson.databind.deser;
+import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
@@ -8,7 +9,7 @@ import com.fasterxml.jackson.annotation.ObjectIdResolver;
import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey;
import com.fasterxml.jackson.core.JsonParser;
-
+import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
@@ -284,7 +285,7 @@ public abstract class DefaultDeserializationContext
/*
/**********************************************************
- /* Extended API
+ /* Extended API, life-cycle
/**********************************************************
*/
@@ -306,6 +307,66 @@ public abstract class DefaultDeserializationContext
/*
/**********************************************************
+ /* Extended API, read methods
+ /**********************************************************
+ */
+
+ public Object readRootValue(JsonParser p, JavaType valueType,
+ JsonDeserializer<Object> deser, Object valueToUpdate)
+ throws IOException
+ {
+ if (_config.useRootWrapping()) {
+ return _unwrapAndDeserialize(p, valueType, deser, valueToUpdate);
+ }
+ if (valueToUpdate == null) {
+ return deser.deserialize(p, this);
+ }
+ return deser.deserialize(p, this, valueToUpdate);
+ }
+
+ protected Object _unwrapAndDeserialize(JsonParser p,
+ JavaType rootType, JsonDeserializer<Object> deser,
+ Object valueToUpdate)
+ throws IOException
+ {
+ PropertyName expRootName = _config.findRootName(rootType);
+ // 12-Jun-2015, tatu: Should try to support namespaces etc but...
+ String expSimpleName = expRootName.getSimpleName();
+ if (p.currentToken() != JsonToken.START_OBJECT) {
+ reportWrongTokenException(rootType, JsonToken.START_OBJECT,
+ "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s",
+ expSimpleName, p.currentToken());
+ }
+ if (p.nextToken() != JsonToken.FIELD_NAME) {
+ reportWrongTokenException(rootType, JsonToken.FIELD_NAME,
+ "Current token not FIELD_NAME (to contain expected root name '%s'), but %s",
+ expSimpleName, p.currentToken());
+ }
+ String actualName = p.getCurrentName();
+ if (!expSimpleName.equals(actualName)) {
+ reportPropertyInputMismatch(rootType, actualName,
+ "Root name '%s' does not match expected ('%s') for type %s",
+ actualName, expSimpleName, rootType);
+ }
+ // ok, then move to value itself....
+ p.nextToken();
+ final Object result;
+ if (valueToUpdate == null) {
+ result = deser.deserialize(p, this);
+ } else {
+ result = deser.deserialize(p, this, valueToUpdate);
+ }
+ // and last, verify that we now get matching END_OBJECT
+ if (p.nextToken() != JsonToken.END_OBJECT) {
+ reportWrongTokenException(rootType, JsonToken.END_OBJECT,
+ "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s",
+ expSimpleName, p.currentToken());
+ }
+ return result;
+ }
+
+ /*
+ /**********************************************************
/* And then the concrete implementation class
/**********************************************************
*/