32
32
import com .fasterxml .jackson .annotation .JsonTypeInfo ;
33
33
import com .fasterxml .jackson .annotation .JsonTypeInfo .As ;
34
34
import com .fasterxml .jackson .core .JsonGenerator ;
35
+ import com .fasterxml .jackson .core .JsonParser ;
36
+ import com .fasterxml .jackson .core .JsonToken ;
35
37
import com .fasterxml .jackson .core .TreeNode ;
36
38
import com .fasterxml .jackson .databind .DeserializationConfig ;
37
39
import com .fasterxml .jackson .databind .JavaType ;
40
+ import com .fasterxml .jackson .databind .JsonDeserializer ;
38
41
import com .fasterxml .jackson .databind .JsonNode ;
39
42
import com .fasterxml .jackson .databind .ObjectMapper ;
40
43
import com .fasterxml .jackson .databind .ObjectMapper .DefaultTyping ;
41
44
import com .fasterxml .jackson .databind .SerializerProvider ;
45
+ import com .fasterxml .jackson .databind .deser .BeanDeserializerFactory ;
46
+ import com .fasterxml .jackson .databind .deser .DefaultDeserializationContext ;
47
+ import com .fasterxml .jackson .databind .deser .std .JsonNodeDeserializer ;
42
48
import com .fasterxml .jackson .databind .jsontype .PolymorphicTypeValidator ;
43
49
import com .fasterxml .jackson .databind .jsontype .TypeDeserializer ;
44
50
import com .fasterxml .jackson .databind .jsontype .TypeSerializer ;
@@ -179,7 +185,7 @@ private static TypeResolver newTypeResolver(ObjectMapper mapper, @Nullable Strin
179
185
Lazy <String > lazyTypeHintPropertyName = typeHintPropertyName != null ? Lazy .of (typeHintPropertyName )
180
186
: newLazyTypeHintPropertyName (mapper , defaultTypingEnabled );
181
187
182
- return new TypeResolver (lazyTypeFactory , lazyTypeHintPropertyName );
188
+ return new TypeResolver (mapper , lazyTypeFactory , lazyTypeHintPropertyName );
183
189
}
184
190
185
191
private static Lazy <String > newLazyTypeHintPropertyName (ObjectMapper mapper , Lazy <Boolean > defaultTypingEnabled ) {
@@ -340,14 +346,13 @@ protected JavaType resolveType(byte[] source, Class<?> type) throws IOException
340
346
*/
341
347
static class TypeResolver {
342
348
343
- // need a separate instance to bypass class hint checks
344
- private final ObjectMapper mapper = new ObjectMapper ();
345
-
349
+ private final ObjectMapper mapper ;
346
350
private final Supplier <TypeFactory > typeFactory ;
347
351
private final Supplier <String > hintName ;
348
352
349
- TypeResolver (Supplier <TypeFactory > typeFactory , Supplier <String > hintName ) {
353
+ TypeResolver (ObjectMapper mapper , Supplier <TypeFactory > typeFactory , Supplier <String > hintName ) {
350
354
355
+ this .mapper = mapper ;
351
356
this .typeFactory = typeFactory ;
352
357
this .hintName = hintName ;
353
358
}
@@ -358,7 +363,7 @@ protected JavaType constructType(Class<?> type) {
358
363
359
364
protected JavaType resolveType (byte [] source , Class <?> type ) throws IOException {
360
365
361
- JsonNode root = mapper . readTree (source );
366
+ JsonNode root = readTree (source );
362
367
JsonNode jsonNode = root .get (hintName .get ());
363
368
364
369
if (jsonNode instanceof TextNode && jsonNode .asText () != null ) {
@@ -367,6 +372,42 @@ protected JavaType resolveType(byte[] source, Class<?> type) throws IOException
367
372
368
373
return constructType (type );
369
374
}
375
+
376
+ /**
377
+ * Lenient variant of ObjectMapper._readTreeAndClose using a strict {@link JsonNodeDeserializer}.
378
+ *
379
+ * @param source
380
+ * @return
381
+ * @throws IOException
382
+ */
383
+ private JsonNode readTree (byte [] source ) throws IOException {
384
+
385
+ JsonDeserializer <? extends JsonNode > deserializer = JsonNodeDeserializer .getDeserializer (JsonNode .class );
386
+ DeserializationConfig cfg = mapper .getDeserializationConfig ();
387
+
388
+ try (JsonParser parser = mapper .createParser (source )) {
389
+
390
+ cfg .initialize (parser );
391
+ JsonToken t = parser .currentToken ();
392
+ if (t == null ) {
393
+ t = parser .nextToken ();
394
+ if (t == null ) {
395
+ return cfg .getNodeFactory ().missingNode ();
396
+ }
397
+ }
398
+
399
+ /*
400
+ * Hokey pokey! Oh my.
401
+ */
402
+ DefaultDeserializationContext ctxt = new DefaultDeserializationContext .Impl (BeanDeserializerFactory .instance )
403
+ .createInstance (cfg , parser , mapper .getInjectableValues ());
404
+ if (t == JsonToken .VALUE_NULL ) {
405
+ return cfg .getNodeFactory ().nullNode ();
406
+ } else {
407
+ return deserializer .deserialize (parser , ctxt );
408
+ }
409
+ }
410
+ }
370
411
}
371
412
372
413
/**
0 commit comments