From e6e73d6c248e201f17ace12229ca2071adb528d7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 13 Jun 2020 13:12:59 -0700 Subject: [PATCH] Continue refactoring --- .../deser/std/NumberDeserializers.java | 28 +++---- .../databind/deser/std/StdDeserializer.java | 73 +++++++++++-------- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java index 2eba63bdc3..cb99a7dbe2 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java @@ -287,8 +287,8 @@ protected Byte _parseByte(DeserializationContext ctxt, JsonParser p) return (Byte) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Byte) _coerceTextualNull(ctxt, false); + if (_checkTextualNull(ctxt, text)) { + return (Byte) getNullValue(ctxt); } int value; try { @@ -367,8 +367,8 @@ protected Short _parseShort(DeserializationContext ctxt, JsonParser p) return (Short) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Short) _coerceTextualNull(ctxt, false); + if (_checkTextualNull(ctxt, text)) { + return (Short) getNullValue(ctxt); } int value; try { @@ -446,8 +446,8 @@ public Character deserialize(JsonParser p, DeserializationContext ctxt) return (Character) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Character) _coerceTextualNull(ctxt, _primitive); + if (_checkTextualNull(ctxt, text)) { + return (Character) getNullValue(ctxt); } // But does it have to be exactly one char? if (text.length() == 1) { @@ -526,8 +526,8 @@ protected final Integer _parseInteger(DeserializationContext ctxt, JsonParser p) return (Integer) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Integer) _coerceTextualNull(ctxt, false); + if (_checkTextualNull(ctxt, text)) { + return (Integer) getNullValue(ctxt); } final int len = text.length(); try { @@ -609,8 +609,8 @@ protected final Long _parseLong(DeserializationContext ctxt, JsonParser p) return (Long) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Long) _coerceTextualNull(ctxt, false); + if (_checkTextualNull(ctxt, text)) { + return (Long) getNullValue(ctxt); } // let's allow Strings to be converted too try { @@ -679,8 +679,8 @@ protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt) return (Float) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Float) _coerceTextualNull(ctxt, false); + if (_checkTextualNull(ctxt, text)) { + return (Float) getNullValue(ctxt); } switch (text.charAt(0)) { case 'I': @@ -770,8 +770,8 @@ protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) t return (Double) getEmptyValue(ctxt); } text = text.trim(); - if (_hasTextualNull(text)) { - return (Double) _coerceTextualNull(ctxt, _primitive); + if (_checkTextualNull(ctxt, text)) { + return (Double) getNullValue(ctxt); } switch (text.charAt(0)) { case 'I': diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java index 1512921282..0b7b562a0d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java @@ -1056,13 +1056,6 @@ protected boolean _hasTextualNull(String value) { return "null".equals(value); } - /** - * @since 2.9 - */ - protected boolean _isEmptyOrTextualNull(String value) { - return value.isEmpty() || "null".equals(value); - } - protected final boolean _isNegInf(String text) { return "-Infinity".equals(text) || "-INF".equals(text); } @@ -1182,6 +1175,25 @@ protected CoercionAction _checkCoercionActionFail(DeserializationContext ctxt, return act; } + /** + * Method called when otherwise unrecognized String value is encountered for + * a non-primitive type: should see if it is String value {@code "null"}, and if so, + * whether it is acceptable according to configuration or not + * + * @since 2.12 + */ + protected boolean _checkTextualNull(DeserializationContext ctxt, String text) + throws JsonMappingException + { + if (_hasTextualNull(text)) { + if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { + _reportFailedNullCoerce(ctxt, true, MapperFeature.ALLOW_COERCION_OF_SCALARS, "String \"null\""); + } + return true; + } + return false; + } + /* /********************************************************************** /* Helper methods for sub-classes, coercions, older (pre-2.12), non-deprecated @@ -1212,29 +1224,13 @@ protected Object _coerceIntegral(JsonParser p, DeserializationContext ctxt) thro } /** - * Method called when JSON String with value "null" is encountered. + * Method called to verify that {@code null} token from input is acceptable + * for primitive (unboxed) target type. It should NOT be called if {@code null} + * was received by other means (coerced due to configuration, or even from + * optionally acceptable String {@code "null"} token). * * @since 2.9 */ - protected Object _coerceTextualNull(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException - { - Enum feat; - boolean enable; - - if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { - feat = MapperFeature.ALLOW_COERCION_OF_SCALARS; - enable = true; - } else if (isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { - feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES; - enable = false; - } else { - return getNullValue(ctxt); - } - _reportFailedNullCoerce(ctxt, enable, feat, "String \"null\""); - return null; - } - - // @since 2.9 protected final void _verifyNullForPrimitive(DeserializationContext ctxt) throws JsonMappingException { if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) { @@ -1244,8 +1240,14 @@ protected final void _verifyNullForPrimitive(DeserializationContext ctxt) throws } } - // NOTE: only for primitive Scalars - // @since 2.9 + /** + * Method called to verify that text value {@code "null"} from input is acceptable + * for primitive (unboxed) target type. It should not be called if actual + * {@code null} token was received, or if null is a result of coercion from + * Some other input type. + * + * @since 2.9 + */ protected final void _verifyNullForPrimitiveCoercion(DeserializationContext ctxt, String str) throws JsonMappingException { Enum feat; @@ -1384,6 +1386,19 @@ protected Object _coerceNullToken(DeserializationContext ctxt, boolean isPrimiti return getNullValue(ctxt); } + @Deprecated // since 2.12 + protected Object _coerceTextualNull(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException { + if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) { + _reportFailedNullCoerce(ctxt, true, MapperFeature.ALLOW_COERCION_OF_SCALARS, "String \"null\""); + } + return getNullValue(ctxt); + } + + @Deprecated // since 2.12 + protected boolean _isEmptyOrTextualNull(String value) { + return value.isEmpty() || "null".equals(value); + } + /* /**************************************************** /* Helper methods for sub-classes, resolving dependencies