From 2e986dfe5937b28ba39b4d28e0f993802c7c9f68 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 28 May 2021 18:55:37 -0700 Subject: [PATCH] Start work on #2989 --- .../jackson/databind/ObjectMapper.java | 34 ++++++++++++------- .../jackson/databind/SerializerProvider.java | 33 +++++++++++++++++- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index 2ca42c7f26..8b19249653 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -3313,11 +3313,19 @@ public T valueToTree(Object fromValue) if (fromValue == null) { return (T) getNodeFactory().nullNode(); } - TokenBuffer buf = new TokenBuffer(this, false); + + // inlined 'writeValue' with minor changes: + // first: disable wrapping when writing + final SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE); + final DefaultSerializerProvider context = _serializerProvider(config); + + // Then create TokenBuffer to use as JsonGenerator + TokenBuffer buf = context.bufferForValueConversion(this); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } try { + context.serializeValue(buf, fromValue); writeValue(buf, fromValue); try (JsonParser p = buf.asParser()) { return readTree(p); @@ -4288,19 +4296,19 @@ public T convertValue(Object fromValue, JavaType toValueType) protected Object _convert(Object fromValue, JavaType toValueType) throws IllegalArgumentException { - // 25-Jan-2019, tatu: [databind#2220] Let's NOT try to short-circuit anything + // inlined 'writeValue' with minor changes: + // first: disable wrapping when writing + final SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE); + final DefaultSerializerProvider context = _serializerProvider(config); - // Then use TokenBuffer, which is a JsonGenerator: - TokenBuffer buf = new TokenBuffer(this, false); + // Then create TokenBuffer to use as JsonGenerator + TokenBuffer buf = context.bufferForValueConversion(this); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } try { - // inlined 'writeValue' with minor changes: - // first: disable wrapping when writing - SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE); // no need to check for closing of TokenBuffer - _serializerProvider(config).serializeValue(buf, fromValue); + context.serializeValue(buf, fromValue); // then matching read, inlined 'readValue' with minor mods: final JsonParser p = buf.asParser(); @@ -4367,14 +4375,16 @@ public T updateValue(T valueToUpdate, Object overrides) { T result = valueToUpdate; if ((valueToUpdate != null) && (overrides != null)) { - TokenBuffer buf = new TokenBuffer(this, false); + final SerializationConfig config = getSerializationConfig(). + without(SerializationFeature.WRAP_ROOT_VALUE); + final DefaultSerializerProvider context = _serializerProvider(config); + // Then create TokenBuffer to use as JsonGenerator + TokenBuffer buf = context.bufferForValueConversion(this); if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { buf = buf.forceUseOfBigDecimal(true); } try { - SerializationConfig config = getSerializationConfig(). - without(SerializationFeature.WRAP_ROOT_VALUE); - _serializerProvider(config).serializeValue(buf, overrides); + context.serializeValue(buf, overrides); JsonParser p = buf.asParser(); result = readerForUpdating(valueToUpdate).readValue(p); p.close(); diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java index e8c26dbb38..34546d02b8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; @@ -26,6 +27,7 @@ import com.fasterxml.jackson.databind.ser.std.NullSerializer; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; +import com.fasterxml.jackson.databind.util.TokenBuffer; /** * Class that defines API used by {@link ObjectMapper} and @@ -458,7 +460,36 @@ public final FilterProvider getFilterProvider() { public JsonGenerator getGenerator() { return null; } - + + /* + /********************************************************************** + /* Factory methods for getting appropriate TokenBuffer instances + /* (possibly overridden based on backend data format) + /********************************************************************** + */ + + /** + * Specialized factory method used when we are converting values and do not + * typically have or use "real" parsers or generators. + * + * @since 3.0 + */ + public TokenBuffer bufferForValueConversion(ObjectCodec oc) { + // false -> no native type/object ids + return new TokenBuffer(oc, false); + } + + + /** + * Specialized factory method used when we are converting values and do not + * typically have or use "real" parsers or generators. + * + * @since 3.0 + */ + public final TokenBuffer bufferForValueConversion() { + return bufferForValueConversion(null); + } + /* /********************************************************** /* Access to Object Id aspects