package com.fasterxml.jackson.databind.deser.std; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; public class StackTraceElementDeserializer extends StdScalarDeserializer { private static final long serialVersionUID = 1L; public StackTraceElementDeserializer() { super(StackTraceElement.class); } @Override public StackTraceElement deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.currentToken(); // Must get an Object if (t == JsonToken.START_OBJECT) { String className = "", methodName = "", fileName = ""; // Java 9 adds couple more things String moduleName = null, moduleVersion = null; String classLoaderName = null; int lineNumber = -1; while ((t = p.nextValue()) != JsonToken.END_OBJECT) { String propName = p.getCurrentName(); // TODO: with Java 8, convert to switch if ("className".equals(propName)) { className = p.getText(); } else if ("classLoaderName".equals(propName)) { classLoaderName = p.getText(); } else if ("fileName".equals(propName)) { fileName = p.getText(); } else if ("lineNumber".equals(propName)) { if (t.isNumeric()) { lineNumber = p.getIntValue(); } else { lineNumber = _parseIntPrimitive(p, ctxt); } } else if ("methodName".equals(propName)) { methodName = p.getText(); } else if ("nativeMethod".equals(propName)) { // no setter, not passed via constructor: ignore } else if ("moduleName".equals(propName)) { moduleName = p.getText(); } else if ("moduleVersion".equals(propName)) { moduleVersion = p.getText(); } else if ("declaringClass".equals(propName) || "format".equals(propName)) { // 01-Nov-2017: [databind#1794] Not sure if we should but... let's prune it for now ; } else { handleUnknownProperty(p, ctxt, _valueClass, propName); } p.skipChildren(); // just in case we might get structured values } return constructValue(ctxt, className, methodName, fileName, lineNumber, moduleName, moduleVersion, classLoaderName); } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) { p.nextToken(); final StackTraceElement value = deserialize(p, ctxt); if (p.nextToken() != JsonToken.END_ARRAY) { handleMissingEndArrayForSingle(p, ctxt); } return value; } return (StackTraceElement) ctxt.handleUnexpectedToken(_valueClass, p); } @Deprecated // since 2.9 protected StackTraceElement constructValue(DeserializationContext ctxt, String className, String methodName, String fileName, int lineNumber, String moduleName, String moduleVersion) { return constructValue(ctxt, className, methodName, fileName, lineNumber, moduleName, moduleVersion, null); } /** * Overridable factory method used for constructing {@link StackTraceElement}s. * * @since 2.8 */ protected StackTraceElement constructValue(DeserializationContext ctxt, String className, String methodName, String fileName, int lineNumber, String moduleName, String moduleVersion, String classLoaderName) { // 21-May-2016, tatu: With Java 9, need to use different constructor, probably // via different module, and throw exception here if extra args passed return new StackTraceElement(className, methodName, fileName, lineNumber); } }