@@ -2,19 +2,21 @@ package com.fasterxml.jackson.module.scala
2
2
3
3
import com .fasterxml .jackson .core .{JsonParser , TreeNode }
4
4
import com .fasterxml .jackson .databind ._
5
+ import com .fasterxml .jackson .databind .`type` .TypeFactory
5
6
import com .fasterxml .jackson .databind .json .JsonMapper
6
7
import com .fasterxml .jackson .databind .jsonFormatVisitors .JsonFormatVisitorWrapper
7
8
8
9
import java .io .{File , InputStream , Reader }
9
10
import java .net .URL
11
+ import scala .reflect .{ClassTag , classTag }
10
12
11
13
object ScalaObjectMapper {
12
14
def :: (o : JsonMapper ) = new Mixin (o)
13
15
final class Mixin private [ScalaObjectMapper ](mapper : JsonMapper )
14
16
extends JsonMapper (mapper.rebuild()) with ScalaObjectMapper
15
17
}
16
18
17
- @ deprecated(" ScalaObjectMapper is deprecated because Manifests are not supported in Scala3" , " 2.12.1" )
19
+ // @deprecated("ScalaObjectMapper is deprecated because Manifests are not supported in Scala3", "2.12.1")
18
20
trait ScalaObjectMapper {
19
21
self : ObjectMapper =>
20
22
@@ -29,36 +31,8 @@ trait ScalaObjectMapper {
29
31
* type (typically <code>java.lang.Class</code>), but without explicit
30
32
* context.
31
33
*/
32
- def constructType [T ](implicit m : Manifest [T ]): JavaType = {
33
- val clazz = m.runtimeClass
34
- if (isArray(clazz)) {
35
- val typeArguments = m.typeArguments.map(constructType(_)).toArray
36
- if (typeArguments.length != 1 ) {
37
- throw new IllegalArgumentException (" Need exactly 1 type parameter for array like types (" + clazz.getName+ " )" )
38
- }
39
- getTypeFactory.constructArrayType(typeArguments(0 ))
40
- } else if (isMapLike(clazz)) {
41
- val typeArguments = m.typeArguments.map(constructType(_)).toArray
42
- if (typeArguments.length != 2 ) {
43
- throw new IllegalArgumentException (" Need exactly 2 type parameters for map like types (" + clazz.getName+ " )" )
44
- }
45
- getTypeFactory.constructMapLikeType(clazz, typeArguments(0 ), typeArguments(1 ))
46
- } else if (isReference(clazz)) { // Option is a subclss of IterableOnce, so check it first
47
- val typeArguments = m.typeArguments.map(constructType(_)).toArray
48
- if (typeArguments.length != 1 ) {
49
- throw new IllegalArgumentException (" Need exactly 1 type parameter for reference types (" + clazz.getName+ " )" )
50
- }
51
- getTypeFactory.constructReferenceType(clazz, typeArguments(0 ))
52
- } else if (isCollectionLike(clazz)) {
53
- val typeArguments = m.typeArguments.map(constructType(_)).toArray
54
- if (typeArguments.length != 1 ) {
55
- throw new IllegalArgumentException (" Need exactly 1 type parameter for collection like types (" + clazz.getName+ " )" )
56
- }
57
- getTypeFactory.constructCollectionLikeType(clazz, typeArguments(0 ))
58
- } else {
59
- val typeArguments = m.typeArguments.map(constructType(_)).toArray
60
- getTypeFactory.constructParametricType(clazz, typeArguments : _* )
61
- }
34
+ def constructType [T ](implicit m : JavaTypeable [T ]): JavaType = {
35
+ m.asJavaType(getTypeFactory)
62
36
}
63
37
64
38
/*
@@ -76,7 +50,7 @@ trait ScalaObjectMapper {
76
50
* and specifically needs to be used if the root type is a
77
51
* parameterized (generic) container type.
78
52
*/
79
- def readValue [T : Manifest ](jp : JsonParser ): T = {
53
+ def readValue [T : JavaTypeable ](jp : JsonParser ): T = {
80
54
readValue(jp, constructType[T ])
81
55
}
82
56
@@ -92,7 +66,7 @@ trait ScalaObjectMapper {
92
66
* <p>
93
67
* Note that [[com.fasterxml.jackson.databind.ObjectReader ]] has more complete set of variants.
94
68
*/
95
- def readValues [T : Manifest ](jp : JsonParser ): MappingIterator [T ] = {
69
+ def readValues [T : JavaTypeable ](jp : JsonParser ): MappingIterator [T ] = {
96
70
readValues(jp, constructType[T ])
97
71
}
98
72
@@ -111,8 +85,8 @@ trait ScalaObjectMapper {
111
85
* objectMapper.convertValue(n, valueClass);
112
86
* </pre>
113
87
*/
114
- def treeToValue [T : Manifest ](n : TreeNode ): T = {
115
- treeToValue(n, manifest [T ].runtimeClass).asInstanceOf [T ]
88
+ def treeToValue [T : ClassTag ](n : TreeNode ): T = {
89
+ treeToValue(n, classTag [T ].runtimeClass).asInstanceOf [T ]
116
90
}
117
91
118
92
/*
@@ -127,63 +101,63 @@ trait ScalaObjectMapper {
127
101
* convenience methods
128
102
**********************************************************
129
103
*/
130
- def readValue [T : Manifest ](src : File ): T = {
104
+ def readValue [T : JavaTypeable ](src : File ): T = {
131
105
readValue(src, constructType[T ])
132
106
}
133
107
134
- def readValue [T : Manifest ](src : URL ): T = {
108
+ def readValue [T : JavaTypeable ](src : URL ): T = {
135
109
readValue(src, constructType[T ])
136
110
}
137
111
138
- def readValue [T : Manifest ](content : String ): T = {
112
+ def readValue [T : JavaTypeable ](content : String ): T = {
139
113
readValue(content, constructType[T ])
140
114
}
141
115
142
- def readValue [T : Manifest ](src : Reader ): T = {
116
+ def readValue [T : JavaTypeable ](src : Reader ): T = {
143
117
readValue(src, constructType[T ])
144
118
}
145
119
146
- def readValue [T : Manifest ](src : InputStream ): T = {
120
+ def readValue [T : JavaTypeable ](src : InputStream ): T = {
147
121
readValue(src, constructType[T ])
148
122
}
149
123
150
- def readValue [T : Manifest ](src : Array [Byte ]): T = {
124
+ def readValue [T : JavaTypeable ](src : Array [Byte ]): T = {
151
125
readValue(src, constructType[T ])
152
126
}
153
127
154
- def readValue [T : Manifest ](src : Array [Byte ], offset : Int , len : Int ): T = {
128
+ def readValue [T : JavaTypeable ](src : Array [Byte ], offset : Int , len : Int ): T = {
155
129
readValue(src, offset, len, constructType[T ])
156
130
}
157
131
158
- def updateValue [T : Manifest ](valueToUpdate : T , src : File ): T = {
132
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : File ): T = {
159
133
objectReaderFor(valueToUpdate).readValue(src)
160
134
}
161
135
162
- def updateValue [T : Manifest ](valueToUpdate : T , src : URL ): T = {
136
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : URL ): T = {
163
137
objectReaderFor(valueToUpdate).readValue(src)
164
138
}
165
139
166
- def updateValue [T : Manifest ](valueToUpdate : T , content : String ): T = {
140
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , content : String ): T = {
167
141
objectReaderFor(valueToUpdate).readValue(content)
168
142
}
169
143
170
- def updateValue [T : Manifest ](valueToUpdate : T , src : Reader ): T = {
144
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Reader ): T = {
171
145
objectReaderFor(valueToUpdate).readValue(src)
172
146
}
173
147
174
- def updateValue [T : Manifest ](valueToUpdate : T , src : InputStream ): T = {
148
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : InputStream ): T = {
175
149
objectReaderFor(valueToUpdate).readValue(src)
176
150
}
177
151
178
- def updateValue [T : Manifest ](valueToUpdate : T , src : Array [Byte ]): T = {
152
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Array [Byte ]): T = {
179
153
objectReaderFor(valueToUpdate).readValue(src)
180
154
}
181
155
182
- def updateValue [T : Manifest ](valueToUpdate : T , src : Array [Byte ], offset : Int , len : Int ): T = {
156
+ def updateValue [T : JavaTypeable ](valueToUpdate : T , src : Array [Byte ], offset : Int , len : Int ): T = {
183
157
objectReaderFor(valueToUpdate).readValue(src, offset, len)
184
158
}
185
159
186
- private def objectReaderFor [T : Manifest ](valueToUpdate : T ): ObjectReader = {
160
+ private def objectReaderFor [T : JavaTypeable ](valueToUpdate : T ): ObjectReader = {
187
161
readerForUpdating(valueToUpdate).forType(constructType[T ])
188
162
}
189
163
@@ -198,8 +172,8 @@ trait ScalaObjectMapper {
198
172
* Factory method for constructing [[com.fasterxml.jackson.databind.ObjectWriter ]] that will
199
173
* serialize objects using specified JSON View (filter).
200
174
*/
201
- def writerWithView [T : Manifest ]: ObjectWriter = {
202
- writerWithView(manifest [T ].runtimeClass)
175
+ def writerWithView [T : ClassTag ]: ObjectWriter = {
176
+ writerWithView(classTag [T ].runtimeClass)
203
177
}
204
178
205
179
/**
@@ -213,7 +187,7 @@ trait ScalaObjectMapper {
213
187
*
214
188
* @since 2.5
215
189
*/
216
- def writerFor [T : Manifest ]: ObjectWriter = {
190
+ def writerFor [T : JavaTypeable ]: ObjectWriter = {
217
191
writerFor(constructType[T ])
218
192
}
219
193
@@ -228,16 +202,16 @@ trait ScalaObjectMapper {
228
202
* Factory method for constructing [[com.fasterxml.jackson.databind.ObjectReader ]] that will
229
203
* read or update instances of specified type
230
204
*/
231
- def readerFor [T : Manifest ]: ObjectReader = {
205
+ def readerFor [T : JavaTypeable ]: ObjectReader = {
232
206
readerFor(constructType[T ])
233
207
}
234
208
235
209
/**
236
210
* Factory method for constructing [[com.fasterxml.jackson.databind.ObjectReader ]] that will
237
211
* deserialize objects using specified JSON View (filter).
238
212
*/
239
- def readerWithView [T : Manifest ]: ObjectReader = {
240
- readerWithView(manifest [T ].runtimeClass)
213
+ def readerWithView [T : ClassTag ]: ObjectReader = {
214
+ readerWithView(classTag [T ].runtimeClass)
241
215
}
242
216
243
217
/*
@@ -258,7 +232,7 @@ trait ScalaObjectMapper {
258
232
* if so, root cause will contain underlying checked exception data binding
259
233
* functionality threw
260
234
*/
261
- def convertValue [T : Manifest ](fromValue : Any ): T = {
235
+ def convertValue [T : JavaTypeable ](fromValue : Any ): T = {
262
236
convertValue(fromValue, constructType[T ])
263
237
}
264
238
@@ -279,26 +253,109 @@ trait ScalaObjectMapper {
279
253
*
280
254
* @since 2.1
281
255
*/
282
- def acceptJsonFormatVisitor [T : Manifest ](visitor : JsonFormatVisitorWrapper ): Unit = {
283
- acceptJsonFormatVisitor(manifest [T ].runtimeClass, visitor)
256
+ def acceptJsonFormatVisitor [T : ClassTag ](visitor : JsonFormatVisitorWrapper ): Unit = {
257
+ acceptJsonFormatVisitor(classTag [T ].runtimeClass, visitor)
284
258
}
285
259
286
- private def isArray (c : Class [_]): Boolean = {
287
- c.isArray
260
+ }
261
+
262
+ trait JavaTypeable [T ] {
263
+ def asJavaType (typeFactory : TypeFactory ): JavaType
264
+ }
265
+
266
+ object JavaTypeable {
267
+
268
+ implicit val anyJavaTypeable : JavaTypeable [Any ] = {
269
+ new JavaTypeable [Any ] {
270
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
271
+ val typeArgs : Array [JavaType ] = Array ()
272
+ typeFactory.constructParametricType(classOf [Object ], typeArgs : _* )
273
+ }
274
+ }
288
275
}
289
276
290
- private val MAP = classOf [collection.Map [_,_]]
291
- private def isMapLike (c : Class [_]): Boolean = {
292
- MAP .isAssignableFrom(c)
277
+ implicit def optionJavaTypeable [T : JavaTypeable ]: JavaTypeable [Option [T ]] = {
278
+ new JavaTypeable [Option [T ]] {
279
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
280
+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
281
+ typeFactory.constructReferenceType(classOf [Option [_]], typeArg0)
282
+ }
283
+ }
293
284
}
294
285
295
- private val OPTION = classOf [Option [_]]
296
- private def isReference (c : Class [_]): Boolean = {
297
- OPTION .isAssignableFrom(c)
286
+ implicit def arrayJavaTypeable [T : JavaTypeable ]: JavaTypeable [Array [T ]] = {
287
+ new JavaTypeable [Array [T ]] {
288
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
289
+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
290
+ typeFactory.constructArrayType(typeArg0)
291
+ }
292
+ }
298
293
}
299
294
300
- private val ITERABLE = classOf [collection.Iterable [_]]
301
- private def isCollectionLike (c : Class [_]): Boolean = {
302
- ITERABLE .isAssignableFrom(c)
295
+ implicit def mapJavaTypeable [M [_,_] <: Map [_,_], K : JavaTypeable , V : JavaTypeable ](implicit ct : ClassTag [M [K ,V ]]): JavaTypeable [M [K , V ]] = {
296
+ new JavaTypeable [M [K , V ]] {
297
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
298
+ val typeArg0 = implicitly[JavaTypeable [K ]].asJavaType(typeFactory)
299
+ val typeArg1 = implicitly[JavaTypeable [V ]].asJavaType(typeFactory)
300
+ typeFactory.constructMapLikeType(ct.runtimeClass, typeArg0, typeArg1)
301
+ }
302
+ }
303
303
}
304
+
305
+ implicit def collectionJavaTypeable [I [_] <: Iterable [_], T : JavaTypeable ](implicit ct : ClassTag [I [T ]]): JavaTypeable [I [T ]] = {
306
+ new JavaTypeable [I [T ]] {
307
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
308
+ val typeArg0 = implicitly[JavaTypeable [T ]].asJavaType(typeFactory)
309
+ typeFactory.constructCollectionLikeType(ct.runtimeClass, typeArg0)
310
+ }
311
+ }
312
+ }
313
+
314
+ // TODO generate genX for X up to a large enough number, 10? 22?
315
+
316
+ implicit def gen3JavaTypeable [T [_, _, _], A : JavaTypeable , B : JavaTypeable , C : JavaTypeable ](implicit ct : ClassTag [T [A , B , C ]]): JavaTypeable [T [A , B , C ]] = {
317
+ new JavaTypeable [T [A , B , C ]] {
318
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
319
+ val typeArgs : Array [JavaType ] = Array (
320
+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
321
+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory),
322
+ implicitly[JavaTypeable [C ]].asJavaType(typeFactory)
323
+ )
324
+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
325
+ }
326
+ }
327
+ }
328
+
329
+ implicit def gen2JavaTypeable [T [_, _], A : JavaTypeable , B : JavaTypeable ](implicit ct : ClassTag [T [A , B ]]): JavaTypeable [T [A , B ]] = {
330
+ new JavaTypeable [T [A , B ]] {
331
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
332
+ val typeArgs : Array [JavaType ] = Array (
333
+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory),
334
+ implicitly[JavaTypeable [B ]].asJavaType(typeFactory)
335
+ )
336
+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
337
+ }
338
+ }
339
+ }
340
+
341
+ implicit def gen1JavaTypeable [T [_], A : JavaTypeable ](implicit ct : ClassTag [T [A ]]): JavaTypeable [T [A ]] = {
342
+ new JavaTypeable [T [A ]] {
343
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
344
+ val typeArgs : Array [JavaType ] = Array (
345
+ implicitly[JavaTypeable [A ]].asJavaType(typeFactory)
346
+ )
347
+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
348
+ }
349
+ }
350
+ }
351
+
352
+ implicit def gen0JavaTypeable [T ](implicit ct : ClassTag [T ]): JavaTypeable [T ] = {
353
+ new JavaTypeable [T ] {
354
+ override def asJavaType (typeFactory : TypeFactory ): JavaType = {
355
+ val typeArgs : Array [JavaType ] = Array ()
356
+ typeFactory.constructParametricType(ct.runtimeClass, typeArgs : _* )
357
+ }
358
+ }
359
+ }
360
+
304
361
}
0 commit comments