30
30
import tools .jackson .databind .ValueSerializer ;
31
31
import tools .jackson .databind .cfg .MapperBuilder ;
32
32
import tools .jackson .databind .deser .jdk .JavaUtilCalendarDeserializer ;
33
+ import tools .jackson .databind .deser .jdk .JavaUtilDateDeserializer ;
34
+ import tools .jackson .databind .deser .jdk .NumberDeserializers .BigDecimalDeserializer ;
35
+ import tools .jackson .databind .deser .jdk .NumberDeserializers .BigIntegerDeserializer ;
36
+ import tools .jackson .databind .deser .std .StdDeserializer ;
37
+ import tools .jackson .databind .exc .MismatchedInputException ;
33
38
import tools .jackson .databind .json .JsonMapper ;
34
39
import tools .jackson .databind .json .JsonMapper .Builder ;
35
40
import tools .jackson .databind .jsontype .BasicPolymorphicTypeValidator ;
41
+ import tools .jackson .databind .jsontype .TypeDeserializer ;
42
+ import tools .jackson .databind .jsontype .TypeSerializer ;
43
+ import tools .jackson .databind .jsontype .impl .AsPropertyTypeDeserializer ;
36
44
import tools .jackson .databind .module .SimpleDeserializers ;
37
45
import tools .jackson .databind .module .SimpleSerializers ;
38
46
import tools .jackson .databind .ser .Serializers ;
39
47
import tools .jackson .databind .ser .jdk .JavaUtilCalendarSerializer ;
40
48
import tools .jackson .databind .ser .jdk .JavaUtilDateSerializer ;
41
49
50
+ import java .math .BigDecimal ;
51
+ import java .math .BigInteger ;
42
52
import java .time .ZoneId ;
43
53
import java .util .ArrayList ;
44
54
import java .util .Arrays ;
45
55
import java .util .Calendar ;
56
+ import java .util .Collection ;
46
57
import java .util .Collections ;
47
- import java .util .GregorianCalendar ;
58
+ import java .util .Date ;
48
59
import java .util .HashMap ;
49
60
import java .util .Iterator ;
50
61
import java .util .LinkedHashMap ;
@@ -176,10 +187,9 @@ public Jackson3HashMapper(
176
187
public static void preconfigure (MapperBuilder <? extends ObjectMapper , ? extends MapperBuilder <?, ?>> builder ) {
177
188
builder .findAndAddModules ().addModules (new HashMapperModule ())
178
189
.activateDefaultTypingAsProperty (BasicPolymorphicTypeValidator .builder ().allowIfBaseType (Object .class )
179
- .allowIfSubType ((ctx , clazz ) -> true ).build (), DefaultTyping .NON_FINAL_AND_ENUMS , "@class" )
190
+ .allowIfSubType ((ctx , clazz ) -> true ).build (), DefaultTyping .NON_FINAL , "@class" )
180
191
.configure (DeserializationFeature .FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY , false )
181
192
.configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false )
182
- //.configure(DeserializationFeature., false)
183
193
.changeDefaultPropertyInclusion (value -> value .withValueInclusion (Include .NON_NULL ));
184
194
}
185
195
@@ -197,7 +207,7 @@ public Jackson3HashMapper(ObjectMapper mapper, boolean flatten) {
197
207
198
208
this .flatten = flatten ;
199
209
this .typingMapper = mapper ;
200
- this .untypedMapper = mapper . rebuild (). deactivateDefaultTyping (). build ();
210
+ this .untypedMapper = JsonMapper . shared ();
201
211
}
202
212
203
213
@ Override
@@ -216,7 +226,6 @@ public Object fromHash(Map<String, Object> hash) {
216
226
if (this .flatten ) {
217
227
218
228
Map <String , Object > unflattenedHash = doUnflatten (hash );
219
- System .out .println ("unflat: " + unflattenedHash );
220
229
byte [] unflattenedHashedBytes = this .untypedMapper .writeValueAsBytes (unflattenedHash );
221
230
Object hashedObject = this .typingMapper .reader ().forType (Object .class ).readValue (unflattenedHashedBytes );
222
231
@@ -328,9 +337,7 @@ private void doFlatten(String propertyPrefix, Set<Entry<String, JsonNode>> input
328
337
propertyPrefix = propertyPrefix + "." ;
329
338
}
330
339
331
- Iterator <Entry <String , JsonNode >> entries = inputMap .iterator ();
332
- while (entries .hasNext ()) {
333
- Entry <String , JsonNode > entry = entries .next ();
340
+ for (Entry <String , JsonNode > entry : inputMap ) {
334
341
flattenElement (propertyPrefix + entry .getKey (), entry .getValue (), resultMap );
335
342
}
336
343
}
@@ -351,24 +358,24 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
351
358
JsonNode currentNode = nodes .next ();
352
359
353
360
if (currentNode .isArray ()) {
354
- flattenCollection (propertyPrefix , currentNode .values (). iterator () , resultMap );
361
+ flattenCollection (propertyPrefix , currentNode .values (), resultMap );
355
362
} else if (nodes .hasNext () && mightBeJavaType (currentNode )) {
356
363
357
364
JsonNode next = nodes .next ();
358
365
359
366
if (next .isArray ()) {
360
- flattenCollection (propertyPrefix , next .values (). iterator () , resultMap );
367
+ flattenCollection (propertyPrefix , next .values (), resultMap );
361
368
}
362
- if (currentNode .asText ().equals ("java.util.Date" )) {
363
- resultMap .put (propertyPrefix , next .asText ());
369
+ if (currentNode .asString ().equals ("java.util.Date" )) {
370
+ resultMap .put (propertyPrefix , next .asString ());
364
371
break ;
365
372
}
366
373
if (next .isNumber ()) {
367
374
resultMap .put (propertyPrefix , next .numberValue ());
368
375
break ;
369
376
}
370
- if (next .isTextual ()) {
371
- resultMap .put (propertyPrefix , next .textValue ());
377
+ if (next .isString ()) {
378
+ resultMap .put (propertyPrefix , next .stringValue ());
372
379
break ;
373
380
}
374
381
if (next .isBoolean ()) {
@@ -392,7 +399,7 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
392
399
} else {
393
400
394
401
switch (element .getNodeType ()) {
395
- case STRING -> resultMap .put (propertyPrefix , element .textValue ());
402
+ case STRING -> resultMap .put (propertyPrefix , element .stringValue ());
396
403
case NUMBER -> resultMap .put (propertyPrefix , element .numberValue ());
397
404
case BOOLEAN -> resultMap .put (propertyPrefix , element .booleanValue ());
398
405
case BINARY -> {
@@ -410,7 +417,7 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
410
417
411
418
private boolean mightBeJavaType (JsonNode node ) {
412
419
413
- String textValue = node .asText ();
420
+ String textValue = node .asString ();
414
421
415
422
if (!SOURCE_VERSION_PRESENT ) {
416
423
return Arrays .asList ("java.util.Date" , "java.math.BigInteger" , "java.math.BigDecimal" ).contains (textValue );
@@ -419,10 +426,11 @@ private boolean mightBeJavaType(JsonNode node) {
419
426
return javax .lang .model .SourceVersion .isName (textValue );
420
427
}
421
428
422
- private void flattenCollection (String propertyPrefix , Iterator <JsonNode > list , Map <String , Object > resultMap ) {
429
+ private void flattenCollection (String propertyPrefix , Collection <JsonNode > list , Map <String , Object > resultMap ) {
423
430
424
- for (int counter = 0 ; list .hasNext (); counter ++) {
425
- JsonNode element = list .next ();
431
+ Iterator <JsonNode > iterator = list .iterator ();
432
+ for (int counter = 0 ; iterator .hasNext (); counter ++) {
433
+ JsonNode element = iterator .next ();
426
434
flattenElement (propertyPrefix + "[" + counter + "]" , element , resultMap );
427
435
}
428
436
}
@@ -473,38 +481,96 @@ public Version version() {
473
481
public void setupModule (SetupContext context ) {
474
482
475
483
List <ValueSerializer <?>> valueSerializers = new ArrayList <>();
476
- valueSerializers .add (new JavaUtilDateSerializer (true , null ));
484
+ valueSerializers .add (new JavaUtilDateSerializer (true , null ) {
485
+ @ Override
486
+ public void serializeWithType (Date value , JsonGenerator g , SerializationContext ctxt , TypeSerializer typeSer )
487
+ throws JacksonException {
488
+ serialize (value , g , ctxt );
489
+ }
490
+ });
477
491
valueSerializers .add (new UTCCalendarSerializer ());
478
492
479
493
Serializers serializers = new SimpleSerializers (valueSerializers );
480
494
context .addSerializers (serializers );
481
495
482
496
Map <Class <?>, ValueDeserializer <?>> valueDeserializers = new LinkedHashMap <>();
483
- valueDeserializers .put (GregorianCalendar .class , new UTCCalendarDeserializer ());
497
+ valueDeserializers .put (java .util .Calendar .class ,
498
+ new UntypedFallbackDeserializer <>(new UntypedUTCCalendarDeserializer ()));
499
+ valueDeserializers .put (java .util .Date .class , new UntypedFallbackDeserializer <>(new JavaUtilDateDeserializer ()));
500
+ valueDeserializers .put (BigInteger .class , new UntypedFallbackDeserializer <>(new BigIntegerDeserializer ()));
501
+ valueDeserializers .put (BigDecimal .class , new UntypedFallbackDeserializer <>(new BigDecimalDeserializer ()));
484
502
485
503
context .addDeserializers (new SimpleDeserializers (valueDeserializers ));
486
504
}
505
+
506
+ }
507
+
508
+ static class UntypedFallbackDeserializer <T > extends StdDeserializer <T > {
509
+
510
+ private final StdDeserializer <?> delegate ;
511
+
512
+ protected UntypedFallbackDeserializer (StdDeserializer <?> delegate ) {
513
+ super (Object .class );
514
+ this .delegate = delegate ;
515
+ }
516
+
517
+ @ Override
518
+ public Object deserializeWithType (JsonParser p , DeserializationContext ctxt , TypeDeserializer typeDeserializer )
519
+ throws JacksonException {
520
+
521
+ if (!(typeDeserializer instanceof AsPropertyTypeDeserializer asPropertySerializer )) {
522
+ return super .deserializeWithType (p , ctxt , typeDeserializer );
523
+ }
524
+
525
+ try {
526
+ return super .deserializeWithType (p , ctxt , typeDeserializer );
527
+ } catch (MismatchedInputException e ) {
528
+ if (!asPropertySerializer .baseType ().isTypeOrSuperTypeOf (delegate .handledType ())) {
529
+ throw e ;
530
+ }
531
+ }
532
+
533
+ return deserialize (p , ctxt );
534
+
535
+ }
536
+
537
+ @ Override
538
+ @ SuppressWarnings ("unchecked" )
539
+ public T deserialize (JsonParser p , DeserializationContext ctxt ) throws JacksonException {
540
+ return (T ) delegate .deserialize (p , ctxt );
541
+ }
487
542
}
488
543
489
544
static class UTCCalendarSerializer extends JavaUtilCalendarSerializer {
490
545
546
+ private static final TimeZone UTC = TimeZone .getTimeZone ("UTC" );
547
+
491
548
@ Override
492
549
public void serialize (Calendar value , JsonGenerator g , SerializationContext provider ) throws JacksonException {
493
550
494
551
Calendar utc = Calendar .getInstance ();
495
552
utc .setTimeInMillis (value .getTimeInMillis ());
496
- utc .setTimeZone (TimeZone . getTimeZone ( " UTC" ) );
553
+ utc .setTimeZone (UTC );
497
554
super .serialize (utc , g , provider );
498
555
}
556
+
557
+ @ Override
558
+ public void serializeWithType (Calendar value , JsonGenerator g , SerializationContext ctxt , TypeSerializer typeSer )
559
+ throws JacksonException {
560
+ serialize (value , g , ctxt );
561
+ }
499
562
}
500
563
501
- static class UTCCalendarDeserializer extends JavaUtilCalendarDeserializer {
564
+ static class UntypedUTCCalendarDeserializer extends JavaUtilCalendarDeserializer {
565
+
566
+ private static final TimeZone UTC = TimeZone .getTimeZone ("UTC" );
567
+
502
568
@ Override
503
569
public Calendar deserialize (JsonParser p , DeserializationContext ctxt ) throws JacksonException {
504
570
505
571
Calendar cal = super .deserialize (p , ctxt );
506
572
507
- Calendar utc = Calendar .getInstance (TimeZone . getTimeZone ( " UTC" ) );
573
+ Calendar utc = Calendar .getInstance (UTC );
508
574
utc .setTimeInMillis (cal .getTimeInMillis ());
509
575
utc .setTimeZone (TimeZone .getTimeZone (ZoneId .systemDefault ()));
510
576
0 commit comments