@@ -2,6 +2,7 @@ package com.fasterxml.jackson.module.scala
22
33import com .fasterxml .jackson .core .{JsonParser , TreeNode }
44import com .fasterxml .jackson .databind ._
5+ import com .fasterxml .jackson .databind .`type` .TypeFactory
56import com .fasterxml .jackson .databind .json .JsonMapper
67
78import java .io .{File , InputStream , Reader }
@@ -15,11 +16,8 @@ object ClassTagExtensions {
1516}
1617
1718/**
18- * Experimental ClassTag equivalent of ScalaObjectMapper. This does not do a good job with
19- * reference types that wrap primitives, eg Option[Int], Seq[Boolean].
20- *
21- * This is because ClassTags only provide access to the Java class and information
22- * about the wrapped types is lost due to type erasure.
19+ * Experimental ClassTag equivalent of ScalaObjectMapper.
20+ * This only works with non parameterized types or parameterized types up to 5 type parameters.
2321 */
2422trait ClassTagExtensions {
2523 self : ObjectMapper =>
@@ -56,6 +54,15 @@ trait ClassTagExtensions {
5654 **********************************************************
5755 */
5856
57+ /**
58+ * Convenience method for constructing [[com.fasterxml.jackson.databind.JavaType ]] out of given
59+ * type (typically <code>java.lang.Class</code>), but without explicit
60+ * context.
61+ */
62+ def constructType [T : JavaTypeable ]: JavaType = {
63+ implicitly[JavaTypeable [T ]].asJavaType(getTypeFactory)
64+ }
65+
5966 /*
6067 **********************************************************
6168 * Public API (from ObjectCodec): deserialization
@@ -71,8 +78,8 @@ trait ClassTagExtensions {
7178 * and specifically needs to be used if the root type is a
7279 * parameterized (generic) container type.
7380 */
74- def readValue [T : ClassTag ](jp : JsonParser ): T = {
75- readValue(jp, classFor [T ])
81+ def readValue [T : JavaTypeable ](jp : JsonParser ): T = {
82+ readValue(jp, constructType [T ])
7683 }
7784
7885 /**
@@ -87,8 +94,8 @@ trait ClassTagExtensions {
8794 * <p>
8895 * Note that [[com.fasterxml.jackson.databind.ObjectReader ]] has more complete set of variants.
8996 */
90- def readValues [T : ClassTag ](jp : JsonParser ): MappingIterator [T ] = {
91- readValues(jp, classFor [T ])
97+ def readValues [T : JavaTypeable ](jp : JsonParser ): MappingIterator [T ] = {
98+ readValues(jp, constructType [T ])
9299 }
93100
94101 /*
@@ -116,64 +123,64 @@ trait ClassTagExtensions {
116123 * convenience methods
117124 **********************************************************
118125 */
119- def readValue [T : ClassTag ](src : File ): T = {
120- readValue(src, classFor [T ])
126+ def readValue [T : JavaTypeable ](src : File ): T = {
127+ readValue(src, constructType [T ])
121128 }
122129
123- def readValue [T : ClassTag ](src : URL ): T = {
124- readValue(src, classFor [T ])
130+ def readValue [T : JavaTypeable ](src : URL ): T = {
131+ readValue(src, constructType [T ])
125132 }
126133
127- def readValue [T : ClassTag ](content : String ): T = {
128- readValue(content, classFor [T ])
134+ def readValue [T : JavaTypeable ](content : String ): T = {
135+ readValue(content, constructType [T ])
129136 }
130137
131- def readValue [T : ClassTag ](src : Reader ): T = {
132- readValue(src, classFor [T ])
138+ def readValue [T : JavaTypeable ](src : Reader ): T = {
139+ readValue(src, constructType [T ])
133140 }
134141
135- def readValue [T : ClassTag ](src : InputStream ): T = {
136- readValue(src, classFor [T ])
142+ def readValue [T : JavaTypeable ](src : InputStream ): T = {
143+ readValue(src, constructType [T ])
137144 }
138145
139- def readValue [T : ClassTag ](src : Array [Byte ]): T = {
140- readValue(src, classFor [T ])
146+ def readValue [T : JavaTypeable ](src : Array [Byte ]): T = {
147+ readValue(src, constructType [T ])
141148 }
142149
143- def readValue [T : ClassTag ](src : Array [Byte ], offset : Int , len : Int ): T = {
144- readValue(src, offset, len, classFor [T ])
150+ def readValue [T : JavaTypeable ](src : Array [Byte ], offset : Int , len : Int ): T = {
151+ readValue(src, offset, len, constructType [T ])
145152 }
146153
147- def updateValue [T : ClassTag ](valueToUpdate : T , src : File ): T = {
154+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : File ): T = {
148155 objectReaderFor(valueToUpdate).readValue(src)
149156 }
150157
151- def updateValue [T : ClassTag ](valueToUpdate : T , src : URL ): T = {
158+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : URL ): T = {
152159 objectReaderFor(valueToUpdate).readValue(src)
153160 }
154161
155- def updateValue [T : ClassTag ](valueToUpdate : T , content : String ): T = {
162+ def updateValue [T : JavaTypeable ](valueToUpdate : T , content : String ): T = {
156163 objectReaderFor(valueToUpdate).readValue(content)
157164 }
158165
159- def updateValue [T : ClassTag ](valueToUpdate : T , src : Reader ): T = {
166+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Reader ): T = {
160167 objectReaderFor(valueToUpdate).readValue(src)
161168 }
162169
163- def updateValue [T : ClassTag ](valueToUpdate : T , src : InputStream ): T = {
170+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : InputStream ): T = {
164171 objectReaderFor(valueToUpdate).readValue(src)
165172 }
166173
167- def updateValue [T : ClassTag ](valueToUpdate : T , src : Array [Byte ]): T = {
174+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Array [Byte ]): T = {
168175 objectReaderFor(valueToUpdate).readValue(src)
169176 }
170177
171- def updateValue [T : ClassTag ](valueToUpdate : T , src : Array [Byte ], offset : Int , len : Int ): T = {
178+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Array [Byte ], offset : Int , len : Int ): T = {
172179 objectReaderFor(valueToUpdate).readValue(src, offset, len)
173180 }
174181
175- private def objectReaderFor [T : ClassTag ](valueToUpdate : T ): ObjectReader = {
176- readerForUpdating(valueToUpdate).forType(classFor [T ])
182+ private def objectReaderFor [T : JavaTypeable ](valueToUpdate : T ): ObjectReader = {
183+ readerForUpdating(valueToUpdate).forType(constructType [T ])
177184 }
178185
179186 /*
@@ -202,8 +209,8 @@ trait ClassTagExtensions {
202209 *
203210 * @since 2.5
204211 */
205- def writerFor [T : ClassTag ]: ObjectWriter = {
206- writerFor(classFor [T ])
212+ def writerFor [T : JavaTypeable ]: ObjectWriter = {
213+ writerFor(constructType [T ])
207214 }
208215
209216 /*
@@ -217,8 +224,8 @@ trait ClassTagExtensions {
217224 * Factory method for constructing [[com.fasterxml.jackson.databind.ObjectReader ]] that will
218225 * read or update instances of specified type
219226 */
220- def readerFor [T : ClassTag ]: ObjectReader = {
221- readerFor(classFor [T ])
227+ def readerFor [T : JavaTypeable ]: ObjectReader = {
228+ readerFor(constructType [T ])
222229 }
223230
224231 /**
@@ -247,11 +254,139 @@ trait ClassTagExtensions {
247254 * if so, root cause will contain underlying checked exception data binding
248255 * functionality threw
249256 */
250- def convertValue [T : ClassTag ](fromValue : Any ): T = {
251- convertValue(fromValue, classFor [T ])
257+ def convertValue [T : JavaTypeable ](fromValue : Any ): T = {
258+ convertValue(fromValue, constructType [T ])
252259 }
253260
254261 private def classFor [T : ClassTag ]: Class [T ] = {
255262 implicitly[ClassTag [T ]].runtimeClass.asInstanceOf [Class [T ]]
256263 }
257264}
265+
266+ trait JavaTypeable [T ] {
267+ def asJavaType (typeFactory : TypeFactory ): JavaType
268+ }
269+
270+ object JavaTypeable {
271+
272+ implicit val anyJavaTypeable : JavaTypeable [Any ] = {
273+ new JavaTypeable [Any ] {
274+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
275+ val typeArgs : Array [JavaType ] = Array ()
276+ typeFactory.constructParametricType(classOf [Object ], typeArgs : _* )
277+ }
278+ }
279+ }
280+
281+ implicit def optionJavaTypeable [T : JavaTypeable ]: JavaTypeable [Option [T ]] = {
282+ new JavaTypeable [Option [T ]] {
283+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
284+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
285+ typeFactory.constructReferenceType(classOf [Option [_]], typeArg0)
286+ }
287+ }
288+ }
289+
290+ implicit def arrayJavaTypeable [T : JavaTypeable ]: JavaTypeable [Array [T ]] = {
291+ new JavaTypeable [Array [T ]] {
292+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
293+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
294+ typeFactory.constructArrayType(typeArg0)
295+ }
296+ }
297+ }
298+
299+ implicit def mapJavaTypeable [M [_,_] <: Map [_,_], K : JavaTypeable , V : JavaTypeable ](implicit ct : ClassTag [M [K ,V ]]): JavaTypeable [M [K , V ]] = {
300+ new JavaTypeable [M [K , V ]] {
301+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
302+ val typeArg0 = implicitly[JavaTypeable [K ]].asJavaType(typeFactory)
303+ val typeArg1 = implicitly[JavaTypeable [V ]].asJavaType(typeFactory)
304+ typeFactory.constructMapLikeType(ct.runtimeClass, typeArg0, typeArg1)
305+ }
306+ }
307+ }
308+
309+ implicit def collectionJavaTypeable [I [_] <: Iterable [_], T : JavaTypeable ](implicit ct : ClassTag [I [T ]]): JavaTypeable [I [T ]] = {
310+ new JavaTypeable [I [T ]] {
311+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
312+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
313+ typeFactory.constructCollectionLikeType(ct.runtimeClass, typeArg0)
314+ }
315+ }
316+ }
317+
318+ implicit def gen5JavaTypeable [T [_, _, _, _, _], A : JavaTypeable , B : JavaTypeable , C : JavaTypeable , D : JavaTypeable , E : JavaTypeable ](implicit ct : ClassTag [T [A , B , C , D , E ]]): JavaTypeable [T [A , B , C , D , E ]] = {
319+ new JavaTypeable [T [A , B , C , D , E ]] {
320+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
321+ val typeArgs : Array [JavaType ] = Array (
322+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
323+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory),
324+ implicitly[JavaTypeable [C ]].asJavaType(typeFactory),
325+ implicitly[JavaTypeable [D ]].asJavaType(typeFactory),
326+ implicitly[JavaTypeable [E ]].asJavaType(typeFactory)
327+ )
328+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
329+ }
330+ }
331+ }
332+
333+ implicit def gen4JavaTypeable [T [_, _, _, _], A : JavaTypeable , B : JavaTypeable , C : JavaTypeable , D : JavaTypeable ](implicit ct : ClassTag [T [A , B , C , D ]]): JavaTypeable [T [A , B , C , D ]] = {
334+ new JavaTypeable [T [A , B , C , D ]] {
335+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
336+ val typeArgs : Array [JavaType ] = Array (
337+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
338+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory),
339+ implicitly[JavaTypeable [C ]].asJavaType(typeFactory),
340+ implicitly[JavaTypeable [D ]].asJavaType(typeFactory)
341+ )
342+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
343+ }
344+ }
345+ }
346+
347+ implicit def gen3JavaTypeable [T [_, _, _], A : JavaTypeable , B : JavaTypeable , C : JavaTypeable ](implicit ct : ClassTag [T [A , B , C ]]): JavaTypeable [T [A , B , C ]] = {
348+ new JavaTypeable [T [A , B , C ]] {
349+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
350+ val typeArgs : Array [JavaType ] = Array (
351+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
352+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory),
353+ implicitly[JavaTypeable [C ]].asJavaType(typeFactory)
354+ )
355+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
356+ }
357+ }
358+ }
359+
360+ implicit def gen2JavaTypeable [T [_, _], A : JavaTypeable , B : JavaTypeable ](implicit ct : ClassTag [T [A , B ]]): JavaTypeable [T [A , B ]] = {
361+ new JavaTypeable [T [A , B ]] {
362+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
363+ val typeArgs : Array [JavaType ] = Array (
364+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
365+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory)
366+ )
367+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
368+ }
369+ }
370+ }
371+
372+ implicit def gen1JavaTypeable [T [_], A : JavaTypeable ](implicit ct : ClassTag [T [A ]]): JavaTypeable [T [A ]] = {
373+ new JavaTypeable [T [A ]] {
374+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
375+ val typeArgs : Array [JavaType ] = Array (
376+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory)
377+ )
378+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
379+ }
380+ }
381+ }
382+
383+ implicit def gen0JavaTypeable [T ](implicit ct : ClassTag [T ]): JavaTypeable [T ] = {
384+ new JavaTypeable [T ] {
385+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
386+ val typeArgs : Array [JavaType ] = Array ()
387+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
388+ }
389+ }
390+ }
391+
392+ }
0 commit comments