Top Description Inners Fields Constructors Methods
tools.jackson.module.androidrecord

public Class AndroidRecordModule

extends SimpleModule
Class Inheritance
Imports
java.lang.reflect.*, java.util.*, java.util.stream.Collectors, .Stream, tools.jackson.core.Version, tools.jackson.databind.*, tools.jackson.databind.cfg.MapperBuilder, .MapperConfig, tools.jackson.databind.introspect.*, tools.jackson.databind.module.SimpleModule

Module that allows (de)serialization of records using the canonical constructor and accessors on Android, where java records are supported through desugaring, and Jackson's built-in support for records doesn't work, since the desugared classes have a non-standard super class, and record component-related reflection methods are missing.

See Android Developers Blog article

Note

this module is a no-op when no Android-desugared records are being (de)serialized, so it is safe to use in code shared between Android and non-Android platforms.

Note

the canonical record constructor is identified through matching of parameter names and types with fields. Therefore, this module doesn't allow a deserialized desugared record to have a custom constructor with the same set of parameter names and types as the canonical one. For the same reason, this module requires that desugared canonical record constructor parameter names be stored in class files. Apparently, with Android SDK 34 tooling, that is the case by default. If that ever changes, it may require an explicit setting in build files.

Author
Eran Leshem

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv static class
pack-priv static class
pack-priv static class

Field Summary

Modifier and TypeField and Description
private static final long
Inherited from tools.jackson.databind.module.SimpleModule:
_abstractTypes_defaultNullKeySerializer_defaultNullValueSerializer_deserializerModifier_deserializers_id_keyDeserializers_keySerializers_mixins_name_namingStrategy_serializerModifier_serializers_subtypes_valueInstantiators_version

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
pack-priv static Class<?>
arrayTypeCompat(Class<?> componentType)

pack-priv static Type
pack-priv static Stream<Field>
pack-priv static boolean
public void
setupModule(JacksonModule.SetupContext context)

Overrides tools.jackson.databind.module.SimpleModule.setupModule.

Standard implementation handles registration of all configured customizations: it is important that sub-classes call this implementation (usually before additional custom logic) if they choose to override it; otherwise customizations will not be registered.

Inherited from tools.jackson.databind.module.SimpleModule:
_checkNotNulladdAbstractTypeMappingaddDeserializeraddKeyDeserializeraddKeySerializeraddSerializeraddSerializeraddValueInstantiatorgetModuleNamegetRegistrationIdregisterSubtypesregisterSubtypesregisterSubtypessetAbstractTypessetDefaultNullKeySerializersetDefaultNullValueSerializersetDeserializerModifiersetDeserializerssetKeyDeserializerssetKeySerializerssetMixInAnnotationsetNamingStrategysetSerializerModifiersetSerializerssetValueInstantiatorsversion

Field Detail

serialVersionUIDback to summary
private static final long serialVersionUID

Hides tools.jackson.databind.module.SimpleModule.serialVersionUID.

Constructor Detail

AndroidRecordModuleback to summary
public AndroidRecordModule()

Method Detail

arrayTypeCompatback to summary
pack-priv static Class<?> arrayTypeCompat(Class<?> componentType)
fixAndroidGenericTypeback to summary
pack-priv static Type fixAndroidGenericType(Type type)
getDesugaredRecordComponentsback to summary
pack-priv static Stream<Field> getDesugaredRecordComponents(Class<?> raw)
isDesugaredRecordClassback to summary
pack-priv static boolean isDesugaredRecordClass(Class<?> raw)
setupModuleback to summary
public void setupModule(JacksonModule.SetupContext context)

Overrides tools.jackson.databind.module.SimpleModule.setupModule.

Doc from tools.jackson.databind.module.SimpleModule.setupModule.

Standard implementation handles registration of all configured customizations: it is important that sub-classes call this implementation (usually before additional custom logic) if they choose to override it; otherwise customizations will not be registered.

Annotations
@Override
tools.jackson.module.androidrecord back to summary

pack-priv Class AndroidRecordModule.AndroidRecordAnnotationIntrospector

extends AnnotationIntrospector
Class Inheritance

Field Summary

Modifier and TypeField and Description
private static final long

Constructor Summary

AccessConstructor and Description
pack-priv

Method Summary

Modifier and TypeMethod and Description
public PotentialCreator
findPreferredCreator(MapperConfig<?> config, AnnotatedClass valueClass, List<PotentialCreator> declaredConstructors, List<PotentialCreator> declaredFactories, Optional<PotentialCreator> zeroParamsConstructor)

Overrides tools.jackson.databind.AnnotationIntrospector.findPreferredCreator.

Method called to check if introspector can find a Creator it considers its "Preferred Creator": Creator to use as the primary one, when no Creator has explicit annotation (findCreatorAnnotation returns null).

public Version
version()

Implements abstract tools.jackson.databind.AnnotationIntrospector.version.

Implements tools.jackson.core.Versioned.version.

Method called to detect version of the component that implements this interface; returned version should never be null, but may return specific "not available" instance (see Version for details).

Inherited from tools.jackson.databind.AnnotationIntrospector:
_findAnnotation_hasAnnotation_hasOneOfallIntrospectorsallIntrospectorsfindAndAddVirtualPropertiesfindAutoDetectVisibilityfindClassDescriptionfindContentDeserializerfindContentSerializerfindCreatorAnnotationfindDefaultEnumValuefindDeserializationContentConverterfindDeserializationConverterfindDeserializerfindEnumAliasesfindEnumNamingStrategyfindEnumValuesfindFilterIdfindFormatfindImplicitPropertyNamefindInjectableValuefindKeyDeserializerfindKeySerializerfindMergeInfofindNameForDeserializationfindNameForSerializationfindNamingStrategyfindNullSerializerfindObjectIdInfofindObjectReferenceInfofindPOJOBuilderfindPOJOBuilderConfigfindPolymorphicTypeInfofindPropertyAccessfindPropertyAliasesfindPropertyDefaultValuefindPropertyDescriptionfindPropertyIgnoralByNamefindPropertyInclusionfindPropertyInclusionByNamefindPropertyIndexfindReferenceTypefindRenameByFieldfindRootNamefindSerializationContentConverterfindSerializationConverterfindSerializationPropertyOrderfindSerializationSortAlphabeticallyfindSerializationTypingfindSerializerfindSetterInfofindSubtypesfindTypeIdResolverfindTypeNamefindTypeResolverBuilderfindUnwrappingNameTransformerfindValueInstantiatorfindViewsfindWrapperNamehasAnyGetterhasAnySetterhasAsKeyhasAsValuehasIgnoreMarkerhasRequiredMarkerisAnnotationBundleisIgnorableTypeisTypeIdnopInstancepairrefineDeserializationTyperefineSerializationTyperesolveSetterConflict

Field Detail

serialVersionUIDback to summary
private static final long serialVersionUID

Constructor Detail

AndroidRecordAnnotationIntrospectorback to summary
pack-priv AndroidRecordAnnotationIntrospector()

Method Detail

findPreferredCreatorback to summary
public PotentialCreator findPreferredCreator(MapperConfig<?> config, AnnotatedClass valueClass, List<PotentialCreator> declaredConstructors, List<PotentialCreator> declaredFactories, Optional<PotentialCreator> zeroParamsConstructor)

Overrides tools.jackson.databind.AnnotationIntrospector.findPreferredCreator.

Doc from tools.jackson.databind.AnnotationIntrospector.findPreferredCreator.

Method called to check if introspector can find a Creator it considers its "Preferred Creator": Creator to use as the primary one, when no Creator has explicit annotation (findCreatorAnnotation returns null). Examples of preferred creators include the canonical constructor defined by Java Records; "Data" classes by frameworks like Lombok and JVM languages like Kotlin and Scala (case classes) also have similar concepts. If introspector can determine that one of given PotentialCreators should be considered preferred one, it should return it; if not, it should return null. Note that core databind functionality may call this method even in the presence of explicitly annotated creators; and may or may not use Creator returned depending on other criteria.

Note

when returning chosen Creator, it may be necessary to mark its "mode" with PotentialCreator#overrideMode (especially for "delegating" creators).

Note

method is NOT called for Java Record types; selection of the canonical constructor as the Primary creator is handled directly by POJOPropertiesCollector

Note

was called findDefaultCreator() in Jackson 2.x but was renamed due to possible confusion with 0-argument "default" constructor.

Annotations
@Override
versionback to summary
public Version version()

Implements abstract tools.jackson.databind.AnnotationIntrospector.version.

Implements tools.jackson.core.Versioned.version.

Doc from tools.jackson.core.Versioned.version.

Method called to detect version of the component that implements this interface; returned version should never be null, but may return specific "not available" instance (see Version for details).

Annotations
@Override
tools.jackson.module.androidrecord back to summary

pack-priv Class AndroidRecordModule.AndroidRecordClassIntrospector

extends BasicClassIntrospector
Class Inheritance

Field Summary

Modifier and TypeField and Description
private static final long
Inherited from tools.jackson.databind.introspect.BasicClassIntrospector:
_config_mixInResolver_resolvedDeserBeanDescs_resolvedFullAnnotations_resolvedSerBeanDescs

Constructor Summary

AccessConstructor and Description
public
pack-priv

Method Summary

Modifier and TypeMethod and Description
protected POJOPropertiesCollector
public BasicClassIntrospector
forMapper()

Overrides tools.jackson.databind.introspect.BasicClassIntrospector.forMapper.

Method called to create an instance to be exclusive used by specified mapper.

public BasicClassIntrospector
forOperation(MapperConfig<?> config)

Overrides tools.jackson.databind.introspect.BasicClassIntrospector.forOperation.

Method called to further create an instance to be used for a single operation (read or write, typically matching ObjectMapper readValue() or writeValue()).

Inherited from tools.jackson.databind.introspect.BasicClassIntrospector:
_findStdJdkCollectionDesc_findStdTypeDef_findStdTypeDesc_resolveAnnotatedClass_resolveAnnotatedWithoutSuperTypescollectPropertiesWithBuilderconstructPropertyCollectorintrospectClassAnnotationsintrospectDirectClassAnnotationsintrospectForCreationintrospectForDeserializationintrospectForDeserializationWithBuilderintrospectForSerialization

Field Detail

serialVersionUIDback to summary
private static final long serialVersionUID

Hides tools.jackson.databind.introspect.BasicClassIntrospector.serialVersionUID.

Constructor Detail

AndroidRecordClassIntrospectorback to summary
public AndroidRecordClassIntrospector()
AndroidRecordClassIntrospectorback to summary
pack-priv AndroidRecordClassIntrospector(MapperConfig<?> config)

Method Detail

collectPropertiesback to summary
protected POJOPropertiesCollector collectProperties(JavaType type, AnnotatedClass classDef, boolean forSerialization, String mutatorPrefix)

Overrides tools.jackson.databind.introspect.BasicClassIntrospector.collectProperties.

Annotations
@Override
forMapperback to summary
public BasicClassIntrospector forMapper()

Overrides tools.jackson.databind.introspect.BasicClassIntrospector.forMapper.

Doc from tools.jackson.databind.introspect.ClassIntrospector.forMapper.

Method called to create an instance to be exclusive used by specified mapper. Needed to ensure that no sharing through cache occurs.

Basic implementation just returns instance itself.

Annotations
@Override
forOperationback to summary
public BasicClassIntrospector forOperation(MapperConfig<?> config)

Overrides tools.jackson.databind.introspect.BasicClassIntrospector.forOperation.

Doc from tools.jackson.databind.introspect.ClassIntrospector.forOperation.

Method called to further create an instance to be used for a single operation (read or write, typically matching ObjectMapper readValue() or writeValue()).

Annotations
@Override
tools.jackson.module.androidrecord back to summary

pack-priv final Class AndroidRecordModule.AndroidRecordNaming

extends DefaultAccessorNamingStrategy
Class Inheritance

Field Summary

Modifier and TypeField and Description
private final Set<String>
_componentNames

Names of actual Record components from definition; auto-detected.

Inherited from tools.jackson.databind.introspect.DefaultAccessorNamingStrategy:
_baseNameValidator_config_forClass_getterPrefix_isGetterPrefix_isGettersNonBoolean_mutatorPrefix

Constructor Summary

AccessConstructor and Description
pack-priv

Method Summary

Modifier and TypeMethod and Description
public String
findNameForRegularGetter(AnnotatedMethod am, String name)

Overrides tools.jackson.databind.introspect.DefaultAccessorNamingStrategy.findNameForRegularGetter.

Method called to find whether given method would be considered a "regular" getter method in context of type introspected, and if so, what is the logical property it is associated with (which in turn suggest external name for property)

Note that signature acceptability has already been checked (no arguments, does have a return value) by caller.

Inherited from tools.jackson.databind.introspect.DefaultAccessorNamingStrategy:
_isCglibGetCallbacks_isGroovyMetaClassGetterfindNameForIsGetterfindNameForMutatormodifyFieldNamestdManglePropertyName

Field Detail

_componentNamesback to summary
private final Set<String> _componentNames

Names of actual Record components from definition; auto-detected.

Constructor Detail

AndroidRecordNamingback to summary
pack-priv AndroidRecordNaming(MapperConfig<?> config, AnnotatedClass forClass)

Method Detail

findNameForRegularGetterback to summary
public String findNameForRegularGetter(AnnotatedMethod am, String name)

Overrides tools.jackson.databind.introspect.DefaultAccessorNamingStrategy.findNameForRegularGetter.

Doc from tools.jackson.databind.introspect.AccessorNamingStrategy.findNameForRegularGetter.

Method called to find whether given method would be considered a "regular" getter method in context of type introspected, and if so, what is the logical property it is associated with (which in turn suggest external name for property)

Note that signature acceptability has already been checked (no arguments, does have a return value) by caller.

Note that this method MAY be called for potential "is-getter" methods too (before findNameForIsGetter)

Note that visibility checks are applied separately; strategy does not need to be concerned with that aspect.

Annotations
@Override