diff options
Diffstat (limited to 'src/main/java')
7 files changed, 154 insertions, 31 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java index f9eee8587..8b93b7fd1 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java @@ -93,7 +93,7 @@ public class BeanDeserializerFactory throws JsonMappingException { final DeserializationConfig config = ctxt.getConfig(); - // We may also have custom overrides: + // First: we may also have custom overrides: JsonDeserializer<?> deser = _findCustomBeanDeserializer(type, config, beanDesc); if (deser != null) { // [databind#2392] @@ -104,10 +104,8 @@ public class BeanDeserializerFactory } return (JsonDeserializer<Object>) deser; } - /* One more thing to check: do we have an exception type - * (Throwable or its sub-classes)? If so, need slightly - * different handling. - */ + // One more thing to check: do we have an exception type (Throwable or its + // sub-classes)? If so, need slightly different handling. if (type.isThrowable()) { return buildThrowableDeserializer(ctxt, type, beanDesc); } @@ -139,6 +137,14 @@ public class BeanDeserializerFactory } // For checks like [databind#1599] _validateSubType(ctxt, type, beanDesc); + + // 05-May-2020, tatu: [databind#2683] Let's actually pre-emptively catch + // certain types (for now, java.time.*) to give better error messages + deser = _findUnsupportedTypeDeserializer(ctxt, type, beanDesc); + if (deser != null) { + return (JsonDeserializer<Object>)deser; + } + // Use generic bean introspection to build deserializer return buildBeanDeserializer(ctxt, type, beanDesc); } @@ -181,7 +187,30 @@ public class BeanDeserializerFactory } return deser; } - + + /** + * Helper method called to see if given type, otherwise to be taken as POJO type, + * is "known but not supported" JDK type, and if so, return alternate handler + * (deserializer). + * Initially added to support more meaningful error messages when "Java 8 date/time" + * support module not registered. + * + * @since 2.12 + */ + protected JsonDeserializer<Object> _findUnsupportedTypeDeserializer(DeserializationContext ctxt, + JavaType type, BeanDescription beanDesc) + throws JsonMappingException + { + if (ClassUtil.isJava8TimeClass(type.getRawClass())) { + // 05-May-2020, tatu: Should we check for possible Shape override to "POJO"? + // (to let users force 'serialize-as-POJO'? + return new UnsupportedTypeDeserializer(type, +"Java 8 date/time type "+ClassUtil.getTypeDescription(type) ++" not supported by default: please register module `jackson-datatype-jsr310` to add handling"); + } + return null; + } + protected JavaType materializeAbstractType(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException @@ -434,8 +463,7 @@ public class BeanDeserializerFactory /* /********************************************************** - /* Helper methods for Bean deserializer construction, - /* overridable by sub-classes + /* Helper methods for Bean deserializer construction /********************************************************** */ diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java index 9df6742bd..ba9b55299 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java @@ -4,12 +4,11 @@ import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * Special bogus "serializer" that will throw - * {@link JsonMappingException} if an attempt is made to deserialize + * {@link com.fasterxml.jackson.databind.exc.MismatchedInputException} if an attempt is made to deserialize * a value. This is used as placeholder to avoid NPEs for uninitialized * structured serializers or handlers. */ @@ -20,7 +19,12 @@ public class FailingDeserializer extends StdDeserializer<Object> protected final String _message; public FailingDeserializer(String m) { - super(Object.class); + this(Object.class, m); + } + + // @since 2.12 + public FailingDeserializer(Class<?> rawType, String m) { + super(rawType); _message = m; } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnsupportedTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnsupportedTypeDeserializer.java new file mode 100644 index 000000000..a7a39148b --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnsupportedTypeDeserializer.java @@ -0,0 +1,39 @@ +package com.fasterxml.jackson.databind.deser.impl; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +/** + * Special bogus "serializer" that will throw + * {@link com.fasterxml.jackson.databind.exc.MismatchedInputException} + * if an attempt is made to deserialize a value. + * This is used for "known unknown" types: types that we can recognize + * but can not support easily (or support known to be added via extension + * module). + * + * @since 2.12 + */ +public class UnsupportedTypeDeserializer extends StdDeserializer<Object> +{ + private static final long serialVersionUID = 1L; + + protected final JavaType _type; + + protected final String _message; + + public UnsupportedTypeDeserializer(JavaType t, String m) { + super(t); + _type = t; + _message = m; + } + + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + ctxt.reportBadDefinition(_type, _message); + return null; + } +} diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java index 79c9a96f0..66e682e5f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig; +import com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; @@ -16,6 +17,7 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator; +import com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer; import com.fasterxml.jackson.databind.ser.std.MapSerializer; import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer; import com.fasterxml.jackson.databind.type.ReferenceType; @@ -376,6 +378,12 @@ public class BeanSerializerFactory return prov.getUnknownTypeSerializer(Object.class); // throw new IllegalArgumentException("Cannot create bean serializer for Object.class"); } + + JsonSerializer<?> ser = _findUnsupportedTypeSerializer(prov, type, beanDesc); + if (ser != null) { + return (JsonSerializer<Object>) ser; + } + final SerializationConfig config = prov.getConfig(); BeanSerializerBuilder builder = constructBeanSerializerBuilder(beanDesc); builder.setConfig(config); @@ -447,9 +455,8 @@ public class BeanSerializerFactory } } - JsonSerializer<Object> ser = null; try { - ser = (JsonSerializer<Object>) builder.build(); + ser = builder.build(); } catch (RuntimeException e) { return prov.reportBadTypeDefinition(beanDesc, "Failed to construct BeanSerializer for %s: (%s) %s", beanDesc.getType(), e.getClass().getName(), e.getMessage()); @@ -467,7 +474,7 @@ public class BeanSerializerFactory } } } - return ser; + return (JsonSerializer<Object>) ser; } protected ObjectIdWriter constructObjectIdHandler(SerializerProvider prov, @@ -814,4 +821,19 @@ public class BeanSerializerFactory return pb.buildWriter(prov, propDef, type, annotatedSerializer, typeSer, contentTypeSer, accessor, staticTyping); } + + protected JsonSerializer<?> _findUnsupportedTypeSerializer(SerializerProvider ctxt, + JavaType type, BeanDescription beanDesc) + throws JsonMappingException + { + if (ClassUtil.isJava8TimeClass(type.getRawClass())) { + // 05-May-2020, tatu: Should we check for possible Shape override to "POJO"? + // (to let users force 'serialize-as-POJO'? + return new UnsupportedTypeSerializer(type, +"Java 8 date/time type "+ClassUtil.getTypeDescription(type) ++" not supported by default: please register module `jackson-datatype-jsr310` to add handling"); + } + return null; + + } } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java index 6021fa89e..e047c6010 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java @@ -1,14 +1,11 @@ package com.fasterxml.jackson.databind.ser.impl; import java.io.IOException; -import java.lang.reflect.Type; import com.fasterxml.jackson.core.*; -import com.fasterxml.jackson.databind.JavaType; + import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** @@ -30,19 +27,8 @@ public class FailingSerializer } @Override - public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException - { - provider.reportMappingProblem(_msg); - } - - @Override - public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { - return null; - } - - @Override - public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) + public void serialize(Object value, JsonGenerator g, SerializerProvider ctxt) throws IOException { - ; + ctxt.reportMappingProblem(_msg); } } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnsupportedTypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnsupportedTypeSerializer.java new file mode 100644 index 000000000..b849ee3d2 --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnsupportedTypeSerializer.java @@ -0,0 +1,37 @@ +package com.fasterxml.jackson.databind.ser.impl; + +import java.io.IOException; + +import com.fasterxml.jackson.core.*; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +/** + * Special bogus "serializer" that will throw + * {@link com.fasterxml.jackson.databind.exc.InvalidDefinitionException} if its {@link #serialize} + * gets invoked. Most commonly registered as handler for unknown types, + * as well as for catching unintended usage (like trying to use null + * as Map/Object key). + */ +public class UnsupportedTypeSerializer + extends StdSerializer<Object> +{ + private static final long serialVersionUID = 1L; + + protected final JavaType _type; + + protected final String _message; + + public UnsupportedTypeSerializer(JavaType t, String msg) { + super(Object.class); + _type = t; + _message = msg; + } + + @Override + public void serialize(Object value, JsonGenerator g, SerializerProvider ctxt) throws IOException { + ctxt.reportBadDefinition(_type, _message); + } +} diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java index 2a984dc90..e3fb8caad 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java @@ -1084,6 +1084,13 @@ public final class ClassUtil return rawType.getName().startsWith("java."); } + /** + * @since 2.12 + */ + public static boolean isJava8TimeClass(Class<?> rawType) { + return rawType.getName().startsWith("java.time."); + } + /* /********************************************************** /* Access to various Class definition aspects; possibly |