diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-07-01 17:40:42 -0700 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-07-01 17:40:42 -0700 |
commit | 58c9211bcc04d3bd4e6e726f10997fc7e6538e25 (patch) | |
tree | 6e0ce086287cc3080b079d50e232c41e743a1f68 /src/main/java/com/fasterxml/jackson | |
parent | 3e5b76a69ce9324ccda7c53ddec52e818b207977 (diff) | |
download | jackson-databind-58c9211bcc04d3bd4e6e726f10997fc7e6538e25.tar.gz |
Refactoring to (eventually) allow XmlMapper override wrapped-root handling
Diffstat (limited to 'src/main/java/com/fasterxml/jackson')
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 /********************************************************** */ |