From e3f005bf09975a3de674b44338bc6ca40f8c1efb Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 25 Jan 2019 20:23:13 -0800 Subject: [PATCH] Backport #2220 fix --- release-notes/VERSION-2.x | 1 + .../databind/DeserializationFeature.java | 8 +++++++- .../jackson/databind/ObjectMapper.java | 20 ++++--------------- .../databind/convert/TestBeanConversions.java | 15 +++----------- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 67acc1b746..57ddcba7c3 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -24,6 +24,7 @@ Project: jackson-databind #2211: Change of behavior (2.8 -> 2.9) with `ObjectMapper.readTree(input)` with no content #2217: Suboptimal memory allocation in `TextNode.getBinaryValue()` (reported by Christoph B) +#2220: Force serialization always for `convertValue()`; avoid short-cuts #2223: Add `missingNode()` method in `JsonNodeFactory` #2227: Minor cleanup of exception message for `Enum` binding failure (reported by RightHandedMonkey@github) diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java index 2fe102ec44..cc05d78390 100644 --- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java +++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java @@ -33,7 +33,13 @@ public enum DeserializationFeature implements ConfigFeature * or {@link java.util.Collection} context) is available. * If enabled such values will be deserialized as {@link java.math.BigDecimal}s; * if disabled, will be deserialized as {@link Double}s. - *

+ *

+ * NOTE: one aspect of {@link java.math.BigDecimal} handling that may need + * configuring is whether trailing zeroes are trimmed: + * {@link com.fasterxml.jackson.databind.node.JsonNodeFactory} has + * {@link com.fasterxml.jackson.databind.node.JsonNodeFactory#withExactBigDecimals} for + * changing default behavior (default is for trailing zeroes to be trimmed). + *

* Feature is disabled by default, meaning that "untyped" floating * point numbers will by default be deserialized as {@link Double}s * (choice is for performance reason -- BigDecimals are slower than diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index f41393adcf..1a48ed4bed 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -2688,9 +2688,10 @@ public T treeToValue(TreeNode n, Class valueType) throws JsonProcessingException { try { + // 25-Jan-2019, tatu: [databind#2220] won't prevent existing coercions here // Simple cast when we just want to cast to, say, ObjectNode - // ... one caveat; while everything is Object.class, let's not take shortcut - if (valueType != Object.class && valueType.isAssignableFrom(n.getClass())) { + if (TreeNode.class.isAssignableFrom(valueType) + && valueType.isAssignableFrom(n.getClass())) { return (T) n; } // 20-Apr-2016, tatu: Another thing: for VALUE_EMBEDDED_OBJECT, assume similar @@ -3648,20 +3649,7 @@ public T convertValue(Object fromValue, JavaType toValueType) protected Object _convert(Object fromValue, JavaType toValueType) throws IllegalArgumentException { - // [databind#1433] Do not shortcut null values. - // This defaults primitives and fires deserializer getNullValue hooks. - if (fromValue != null) { - // also, as per [databind#11], consider case for simple cast - // But with caveats: one is that while everything is Object.class, we don't - // want to "optimize" that out; and the other is that we also do not want - // to lose conversions of generic types. - Class targetType = toValueType.getRawClass(); - if (targetType != Object.class - && !toValueType.hasGenericTypes() - && targetType.isAssignableFrom(fromValue.getClass())) { - return fromValue; - } - } + // 25-Jan-2019, tatu: [databind#2220] Let's NOT try to short-circuit anything // Then use TokenBuffer, which is a JsonGenerator: TokenBuffer buf = new TokenBuffer(this, false); diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java index ac08d94e34..d0cb4eccb5 100644 --- a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java +++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java @@ -217,19 +217,10 @@ private void _convertAndVerifyPoint(ObjectMapper m) */ public void testIssue11() throws Exception { - // First the expected use case, Node specification - ObjectNode root = MAPPER.createObjectNode(); - JsonNode n = root; - ObjectNode ob2 = MAPPER.convertValue(n, ObjectNode.class); - assertSame(root, ob2); - - JsonNode n2 = MAPPER.convertValue(n, JsonNode.class); - assertSame(root, n2); - // then some other no-op conversions - String STR = "test"; - CharSequence seq = MAPPER.convertValue(STR, CharSequence.class); - assertSame(STR, seq); + StringBuilder SB = new StringBuilder("test"); + CharSequence seq = MAPPER.convertValue(SB, CharSequence.class); + assertNotSame(SB, seq); // and then something that should NOT use short-cut Leaf l = new Leaf(13);