3030import tools .jackson .databind .ValueSerializer ;
3131import tools .jackson .databind .cfg .MapperBuilder ;
3232import 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 ;
3338import tools .jackson .databind .json .JsonMapper ;
3439import tools .jackson .databind .json .JsonMapper .Builder ;
3540import 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 ;
3644import tools .jackson .databind .module .SimpleDeserializers ;
3745import tools .jackson .databind .module .SimpleSerializers ;
3846import tools .jackson .databind .ser .Serializers ;
3947import tools .jackson .databind .ser .jdk .JavaUtilCalendarSerializer ;
4048import tools .jackson .databind .ser .jdk .JavaUtilDateSerializer ;
4149
50+ import java .math .BigDecimal ;
51+ import java .math .BigInteger ;
4252import java .time .ZoneId ;
4353import java .util .ArrayList ;
4454import java .util .Arrays ;
4555import java .util .Calendar ;
56+ import java .util .Collection ;
4657import java .util .Collections ;
47- import java .util .GregorianCalendar ;
58+ import java .util .Date ;
4859import java .util .HashMap ;
4960import java .util .Iterator ;
5061import java .util .LinkedHashMap ;
@@ -176,10 +187,9 @@ public Jackson3HashMapper(
176187 public static void preconfigure (MapperBuilder <? extends ObjectMapper , ? extends MapperBuilder <?, ?>> builder ) {
177188 builder .findAndAddModules ().addModules (new HashMapperModule ())
178189 .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" )
180191 .configure (DeserializationFeature .FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY , false )
181192 .configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false )
182- //.configure(DeserializationFeature., false)
183193 .changeDefaultPropertyInclusion (value -> value .withValueInclusion (Include .NON_NULL ));
184194 }
185195
@@ -197,7 +207,7 @@ public Jackson3HashMapper(ObjectMapper mapper, boolean flatten) {
197207
198208 this .flatten = flatten ;
199209 this .typingMapper = mapper ;
200- this .untypedMapper = mapper . rebuild (). deactivateDefaultTyping (). build ();
210+ this .untypedMapper = JsonMapper . shared ();
201211 }
202212
203213 @ Override
@@ -216,7 +226,6 @@ public Object fromHash(Map<String, Object> hash) {
216226 if (this .flatten ) {
217227
218228 Map <String , Object > unflattenedHash = doUnflatten (hash );
219- System .out .println ("unflat: " + unflattenedHash );
220229 byte [] unflattenedHashedBytes = this .untypedMapper .writeValueAsBytes (unflattenedHash );
221230 Object hashedObject = this .typingMapper .reader ().forType (Object .class ).readValue (unflattenedHashedBytes );
222231
@@ -328,9 +337,7 @@ private void doFlatten(String propertyPrefix, Set<Entry<String, JsonNode>> input
328337 propertyPrefix = propertyPrefix + "." ;
329338 }
330339
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 ) {
334341 flattenElement (propertyPrefix + entry .getKey (), entry .getValue (), resultMap );
335342 }
336343 }
@@ -351,24 +358,24 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
351358 JsonNode currentNode = nodes .next ();
352359
353360 if (currentNode .isArray ()) {
354- flattenCollection (propertyPrefix , currentNode .values (). iterator () , resultMap );
361+ flattenCollection (propertyPrefix , currentNode .values (), resultMap );
355362 } else if (nodes .hasNext () && mightBeJavaType (currentNode )) {
356363
357364 JsonNode next = nodes .next ();
358365
359366 if (next .isArray ()) {
360- flattenCollection (propertyPrefix , next .values (). iterator () , resultMap );
367+ flattenCollection (propertyPrefix , next .values (), resultMap );
361368 }
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 ());
364371 break ;
365372 }
366373 if (next .isNumber ()) {
367374 resultMap .put (propertyPrefix , next .numberValue ());
368375 break ;
369376 }
370- if (next .isTextual ()) {
371- resultMap .put (propertyPrefix , next .textValue ());
377+ if (next .isString ()) {
378+ resultMap .put (propertyPrefix , next .stringValue ());
372379 break ;
373380 }
374381 if (next .isBoolean ()) {
@@ -392,7 +399,7 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
392399 } else {
393400
394401 switch (element .getNodeType ()) {
395- case STRING -> resultMap .put (propertyPrefix , element .textValue ());
402+ case STRING -> resultMap .put (propertyPrefix , element .stringValue ());
396403 case NUMBER -> resultMap .put (propertyPrefix , element .numberValue ());
397404 case BOOLEAN -> resultMap .put (propertyPrefix , element .booleanValue ());
398405 case BINARY -> {
@@ -410,7 +417,7 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
410417
411418 private boolean mightBeJavaType (JsonNode node ) {
412419
413- String textValue = node .asText ();
420+ String textValue = node .asString ();
414421
415422 if (!SOURCE_VERSION_PRESENT ) {
416423 return Arrays .asList ("java.util.Date" , "java.math.BigInteger" , "java.math.BigDecimal" ).contains (textValue );
@@ -419,10 +426,11 @@ private boolean mightBeJavaType(JsonNode node) {
419426 return javax .lang .model .SourceVersion .isName (textValue );
420427 }
421428
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 ) {
423430
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 ();
426434 flattenElement (propertyPrefix + "[" + counter + "]" , element , resultMap );
427435 }
428436 }
@@ -473,38 +481,96 @@ public Version version() {
473481 public void setupModule (SetupContext context ) {
474482
475483 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+ });
477491 valueSerializers .add (new UTCCalendarSerializer ());
478492
479493 Serializers serializers = new SimpleSerializers (valueSerializers );
480494 context .addSerializers (serializers );
481495
482496 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 ()));
484502
485503 context .addDeserializers (new SimpleDeserializers (valueDeserializers ));
486504 }
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+ }
487542 }
488543
489544 static class UTCCalendarSerializer extends JavaUtilCalendarSerializer {
490545
546+ private static final TimeZone UTC = TimeZone .getTimeZone ("UTC" );
547+
491548 @ Override
492549 public void serialize (Calendar value , JsonGenerator g , SerializationContext provider ) throws JacksonException {
493550
494551 Calendar utc = Calendar .getInstance ();
495552 utc .setTimeInMillis (value .getTimeInMillis ());
496- utc .setTimeZone (TimeZone . getTimeZone ( " UTC" ) );
553+ utc .setTimeZone (UTC );
497554 super .serialize (utc , g , provider );
498555 }
556+
557+ @ Override
558+ public void serializeWithType (Calendar value , JsonGenerator g , SerializationContext ctxt , TypeSerializer typeSer )
559+ throws JacksonException {
560+ serialize (value , g , ctxt );
561+ }
499562 }
500563
501- static class UTCCalendarDeserializer extends JavaUtilCalendarDeserializer {
564+ static class UntypedUTCCalendarDeserializer extends JavaUtilCalendarDeserializer {
565+
566+ private static final TimeZone UTC = TimeZone .getTimeZone ("UTC" );
567+
502568 @ Override
503569 public Calendar deserialize (JsonParser p , DeserializationContext ctxt ) throws JacksonException {
504570
505571 Calendar cal = super .deserialize (p , ctxt );
506572
507- Calendar utc = Calendar .getInstance (TimeZone . getTimeZone ( " UTC" ) );
573+ Calendar utc = Calendar .getInstance (UTC );
508574 utc .setTimeInMillis (cal .getTimeInMillis ());
509575 utc .setTimeZone (TimeZone .getTimeZone (ZoneId .systemDefault ()));
510576
0 commit comments