66import com .fasterxml .jackson .databind .*;
77import com .fasterxml .jackson .databind .deser .Deserializers ;
88import com .fasterxml .jackson .databind .ser .Serializers ;
9+ import com .fasterxml .jackson .databind .ser .std .DateSerializer ;
10+ import com .fasterxml .jackson .databind .ser .std .SqlDateSerializer ;
11+ import com .fasterxml .jackson .databind .ser .std .SqlTimeSerializer ;
912import com .fasterxml .jackson .databind .util .ClassUtil ;
1013
1114/**
@@ -79,16 +82,28 @@ public class OptionalHandlerFactory implements java.io.Serializable
7982 public final static OptionalHandlerFactory instance = new OptionalHandlerFactory ();
8083
8184 // classes from java.sql module, this module may not be present at runtime
82- private final Map <String , String > _sqlClasses ;
85+ private final Map <String , String > _sqlDeserializers ;
86+ private final Map <String , Object > _sqlSerializers ;
87+
88+ private final static String CLS_NAME_JAVA_SQL_TIMESTAMP = "java.sql.Timestamp" ;
89+ private final static String CLS_NAME_JAVA_SQL_DATE = "java.sql.Date" ;
90+ private final static String CLS_NAME_JAVA_SQL_TIME = "java.sql.Time" ;
8391
8492 protected OptionalHandlerFactory () {
85- _sqlClasses = new HashMap <>();
86- try {
87- _sqlClasses .put ("java.sql.Date" ,
88- "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer" );
89- _sqlClasses .put ("java.sql.Timestamp" ,
90- "com.fasterxml.jackson.databind.deser.std.DateDeserializers$TimestampDeserializer" );
91- } catch (Throwable t ) { }
93+ _sqlDeserializers = new HashMap <>();
94+ _sqlDeserializers .put (CLS_NAME_JAVA_SQL_DATE ,
95+ "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer" );
96+ _sqlDeserializers .put (CLS_NAME_JAVA_SQL_TIMESTAMP ,
97+ "com.fasterxml.jackson.databind.deser.std.DateDeserializers$TimestampDeserializer" );
98+
99+ _sqlSerializers = new HashMap <>();
100+ // 09-Jan-2015, tatu: As per [databind#1073], let's try to guard against possibility
101+ // of some environments missing `java.sql.` types
102+
103+ // note: timestamps are very similar to java.util.Date, thus serialized as such
104+ _sqlSerializers .put (CLS_NAME_JAVA_SQL_TIMESTAMP , DateSerializer .instance );
105+ _sqlSerializers .put (CLS_NAME_JAVA_SQL_DATE , "com.fasterxml.jackson.databind.ser.std.SqlDateSerializer" );
106+ _sqlSerializers .put (CLS_NAME_JAVA_SQL_TIME , "com.fasterxml.jackson.databind.ser.std.SqlTimeSerializer" );
92107 }
93108
94109 /*
@@ -114,6 +129,16 @@ public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType typ
114129 }
115130
116131 String className = rawType .getName ();
132+ Object sqlHandler = _sqlSerializers .get (className );
133+
134+ if (sqlHandler != null ) {
135+ if (sqlHandler instanceof JsonSerializer <?>) {
136+ return (JsonSerializer <?>) sqlHandler ;
137+ }
138+ // must be class name otherwise
139+ return (JsonSerializer <?>) instantiate ((String ) sqlHandler , type );
140+ }
141+
117142 String factoryName ;
118143 if (className .startsWith (PACKAGE_PREFIX_JAVAX_XML ) || hasSuperClassStartingWith (rawType , PACKAGE_PREFIX_JAVAX_XML )) {
119144 factoryName = SERIALIZERS_FOR_JAVAX_XML ;
@@ -147,7 +172,7 @@ public JsonDeserializer<?> findDeserializer(JavaType type, DeserializationConfig
147172 return (JsonDeserializer <?>) instantiate (DESERIALIZER_FOR_DOM_DOCUMENT , type );
148173 }
149174 String className = rawType .getName ();
150- final String deserName = _sqlClasses .get (className );
175+ final String deserName = _sqlDeserializers .get (className );
151176 if (deserName != null ) {
152177 return (JsonDeserializer <?>) instantiate (deserName , type );
153178 }
@@ -178,7 +203,7 @@ public boolean hasDeserializerFor(Class<?> valueType) {
178203 return true ;
179204 }
180205 // 06-Nov-2020, tatu: One of "java.sql" types?
181- return _sqlClasses .containsKey (className );
206+ return _sqlDeserializers .containsKey (className );
182207 }
183208
184209 /*
@@ -190,14 +215,25 @@ public boolean hasDeserializerFor(Class<?> valueType) {
190215 private Object instantiate (String className , JavaType valueType )
191216 {
192217 try {
193- return ClassUtil . createInstance (Class .forName (className ), false );
218+ return instantiate (Class .forName (className ), valueType );
194219 } catch (Throwable e ) {
195- throw new IllegalStateException ("Failed to create instance of `"
220+ throw new IllegalStateException ("Failed to find class `"
196221+className +"` for handling values of type " +ClassUtil .getTypeDescription (valueType )
197222+", problem: (" +e .getClass ().getName ()+") " +e .getMessage ());
198223 }
199224 }
200225
226+ private Object instantiate (Class <?> handlerClass , JavaType valueType )
227+ {
228+ try {
229+ return ClassUtil .createInstance (handlerClass , false );
230+ } catch (Throwable e ) {
231+ throw new IllegalStateException ("Failed to create instance of `"
232+ +handlerClass .getName ()+"` for handling values of type " +ClassUtil .getTypeDescription (valueType )
233+ +", problem: (" +e .getClass ().getName ()+") " +e .getMessage ());
234+ }
235+ }
236+
201237 /**
202238 * Since 2.7 we only need to check for class extension, as all implemented
203239 * types are classes, not interfaces. This has performance implications for
0 commit comments