Log can[Se]Deserialize error in Jackson codecs

Closes gh-25892
This commit is contained in:
Rossen Stoyanchev 2020-11-02 17:25:39 +00:00
parent 3eb2c5e22f
commit 0f6038af70
3 changed files with 62 additions and 5 deletions

View File

@ -21,6 +21,7 @@ import java.lang.annotation.Annotation;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
@ -99,8 +100,20 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
JavaType javaType = getObjectMapper().constructType(elementType.getType());
// Skip String: CharSequenceDecoder + "*/*" comes after
return (!CharSequence.class.isAssignableFrom(elementType.toClass()) &&
getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType));
if (CharSequence.class.isAssignableFrom(elementType.toClass()) || !supportsMimeType(mimeType)) {
return false;
}
if (!logger.isDebugEnabled()) {
return getObjectMapper().canDeserialize(javaType);
}
else {
AtomicReference<Throwable> causeRef = new AtomicReference<>();
if (getObjectMapper().canDeserialize(javaType, causeRef)) {
return true;
}
logWarningIfNecessary(javaType, causeRef.get());
return false;
}
}
@Override

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
@ -111,8 +112,23 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
return false;
}
}
return (Object.class == clazz ||
(!String.class.isAssignableFrom(elementType.resolve(clazz)) && getObjectMapper().canSerialize(clazz)));
if (String.class.isAssignableFrom(elementType.resolve(clazz))) {
return false;
}
if (Object.class == clazz) {
return true;
}
if (!logger.isDebugEnabled()) {
return getObjectMapper().canSerialize(clazz);
}
else {
AtomicReference<Throwable> causeRef = new AtomicReference<>();
if (getObjectMapper().canSerialize(clazz, causeRef)) {
return true;
}
logWarningIfNecessary(clazz, causeRef.get());
return false;
}
}
@Override

View File

@ -26,6 +26,7 @@ import java.util.Map;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.logging.Log;
@ -108,7 +109,34 @@ public abstract class Jackson2CodecSupport {
protected boolean supportsMimeType(@Nullable MimeType mimeType) {
return (mimeType == null || this.mimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType)));
if (mimeType == null) {
return true;
}
for (MimeType supportedMimeType : this.mimeTypes) {
if (supportedMimeType.isCompatibleWith(mimeType)) {
return true;
}
}
return false;
}
/**
* Determine whether to log the given exception coming from a
* {@link ObjectMapper#canDeserialize} / {@link ObjectMapper#canSerialize} check.
* @param type the class that Jackson tested for (de-)serializability
* @param cause the Jackson-thrown exception to evaluate
* (typically a {@link JsonMappingException})
* @since 5.3.1
*/
protected void logWarningIfNecessary(Type type, @Nullable Throwable cause) {
if (cause == null) {
return;
}
if (logger.isDebugEnabled()) {
String msg = "Failed to evaluate Jackson " + (type instanceof JavaType ? "de" : "") +
"serialization for type [" + type + "]";
logger.debug(msg, cause);
}
}
protected JavaType getJavaType(Type type, @Nullable Class<?> contextClass) {