CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-fasterxml-jackson-core--jackson-databind

General data-binding functionality for Jackson: works on core streaming API

Pending
Overview
Eval results
Files

modules.mddocs/

Modules

Jackson's module system provides a clean and extensible way to add functionality to ObjectMapper without modifying core classes. Modules can register custom serializers, deserializers, type resolvers, naming strategies, and other components. This system enables both Jackson's own extensions and third-party libraries to integrate seamlessly.

Module Base Class

Module

Module is the abstract base class for all Jackson modules.

public abstract class Module implements Versioned {
    // Module identification
    public abstract String getModuleName();
    public abstract Version version();
    
    // Module setup - called when module is registered
    public abstract void setupModule(SetupContext context);
    
    // Optional setup methods
    public Object getTypeId();
    public Iterable<? extends Deserializer> getDeserializers();
    public Iterable<? extends Serializer> getSerializers();
    public Iterable<? extends BeanDeserializerModifier> getBeanDeserializerModifiers();
    public Iterable<? extends BeanSerializerModifier> getBeanSerializerModifiers();
    
    // Setup context interface
    public static interface SetupContext {
        // Version information
        Version getMapperVersion();
        
        // Configuration access
        MapperConfig<?> getConfig();
        DeserializationConfig getDeserializationConfig();
        SerializationConfig getSerializationConfig();
        TypeFactory getTypeFactory();
        
        // Component registration
        void addDeserializers(Deserializers d);
        void addKeyDeserializers(KeyDeserializers d);
        void addSerializers(Serializers s);
        void addKeySerializers(Serializers s);
        void addBeanDeserializerModifier(BeanDeserializerModifier mod);
        void addBeanSerializerModifier(BeanSerializerModifier mod);
        void addAbstractTypeResolver(AbstractTypeResolver resolver);
        void addTypeModifier(TypeModifier modifier);
        void addValueInstantiators(ValueInstantiators instantiators);
        
        // Configuration modification
        void setClassIntrospector(ClassIntrospector ci);
        void insertAnnotationIntrospector(AnnotationIntrospector ai);
        void appendAnnotationIntrospector(AnnotationIntrospector ai);
        void registerSubtypes(Class<?>... subtypes);
        void registerSubtypes(NamedType... subtypes);
        void registerSubtypes(Collection<Class<?>> subtypes);
        void setMixInAnnotations(Class<?> target, Class<?> mixinSource);
        void addDeserializationProblemHandler(DeserializationProblemHandler handler);
        void setNamingStrategy(PropertyNamingStrategy naming);
        
        // Deprecated methods (for compatibility)
        @Deprecated
        void addBeanSerializerModifier(BeanSerializerModifier modifier);
        @Deprecated  
        void addBeanDeserializerModifier(BeanDeserializerModifier modifier);
    }
}

Simple Module Implementation

SimpleModule

SimpleModule provides a convenient base implementation for creating custom modules.

public class SimpleModule extends Module implements Serializable {
    // Construction
    public SimpleModule();
    public SimpleModule(String name);
    public SimpleModule(String name, Version version);
    public SimpleModule(String name, Version version, Map<Class<?>, JsonDeserializer<?>> deserializers);
    public SimpleModule(String name, Version version, List<JsonSerializer<?>> serializers);
    public SimpleModule(String name, Version version, Map<Class<?>, JsonDeserializer<?>> deserializers, List<JsonSerializer<?>> serializers);
    
    // Module identification
    public String getModuleName();
    public Version version();
    public Object getTypeId();
    
    // Setup
    public void setupModule(SetupContext context);
    
    // Serializer registration
    public SimpleModule addSerializer(JsonSerializer<?> ser);
    public <T> SimpleModule addSerializer(Class<? extends T> type, JsonSerializer<T> ser);
    public SimpleModule addKeySerializer(Class<?> type, JsonSerializer<?> ser);
    
    // Deserializer registration
    public SimpleModule addDeserializer(Class<?> type, JsonDeserializer<?> deser);
    public SimpleModule addKeyDeserializer(Class<?> type, KeyDeserializer deser);
    
    // Abstract type resolution
    public SimpleModule addAbstractTypeMapping(Class<?> superType, Class<?> subType);
    public SimpleModule addAbstractTypeResolver(AbstractTypeResolver resolver);
    
    // Type modification
    public SimpleModule addTypeModifier(TypeModifier modifier);
    
    // Value instantiation
    public SimpleModule addValueInstantiator(Class<?> beanType, ValueInstantiator inst);
    
    // Mix-in annotations
    public SimpleModule setMixInAnnotation(Class<?> targetType, Class<?> mixinClass);
    
    // Naming strategy
    public SimpleModule setNamingStrategy(PropertyNamingStrategy naming);
    
    // Modifier registration
    public SimpleModule setDeserializerModifier(BeanDeserializerModifier mod);
    public SimpleModule setSerializerModifier(BeanSerializerModifier mod);
    
    // Subtype registration
    public SimpleModule registerSubtypes(Class<?>... subtypes);
    public SimpleModule registerSubtypes(NamedType... subtypes);
    public SimpleModule registerSubtypes(Collection<Class<?>> subtypes);
    
    // Introspector modification
    public SimpleModule setClassIntrospector(ClassIntrospector ci);
    public SimpleModule insertAnnotationIntrospector(AnnotationIntrospector ai);
    public SimpleModule appendAnnotationIntrospector(AnnotationIntrospector ai);
    
    // Problem handler registration
    public SimpleModule addDeserializationProblemHandler(DeserializationProblemHandler handler);
}

Component Interfaces

Serializers

Interface for registering custom serializers.

public interface Serializers {
    // Serializer lookup methods
    JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc);
    JsonSerializer<?> findReferenceSerializer(SerializationConfig config, ReferenceType type, BeanDescription beanDesc, TypeSerializer contentTypeSerializer, JsonSerializer<Object> contentValueSerializer);
    JsonSerializer<?> findArraySerializer(SerializationConfig config, ArrayType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer);
    JsonSerializer<?> findCollectionSerializer(SerializationConfig config, CollectionType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer);
    JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer);
    JsonSerializer<?> findMapSerializer(SerializationConfig config, MapType type, BeanDescription beanDesc, JsonSerializer<Object> keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer);
    JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonSerializer<Object> keySerializer, TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer);
    
    // Base implementation
    public static abstract class Base implements Serializers {
        // Default implementations returning null
    }
}

// Utility classes
public class SimpleSerializers extends Serializers.Base {
    // Map-based serializer storage
    public SimpleSerializers();
    public SimpleSerializers(Map<Class<?>, JsonSerializer<?>> serializers);
    
    // Registration methods
    public SimpleSerializers addSerializer(JsonSerializer<?> ser);
    public <T> SimpleSerializers addSerializer(Class<? extends T> type, JsonSerializer<T> ser);
    public void addSerializers(Map<Class<?>, JsonSerializer<?>> serializers);
    
    // Lookup implementation
    public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc);
}

Deserializers

Interface for registering custom deserializers.

public interface Deserializers {
    // Deserializer lookup methods
    JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException;
    JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) throws JsonMappingException;
    JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException;
    JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException;
    
    // Base implementation
    public static abstract class Base implements Deserializers {
        // Default implementations returning null
    }
}

// Utility classes
public class SimpleDeserializers extends Deserializers.Base {
    // Map-based deserializer storage
    public SimpleDeserializers();
    public SimpleDeserializers(Map<Class<?>, JsonDeserializer<?>> deserializers);
    
    // Registration methods  
    public SimpleDeserializers addDeserializer(Class<?> type, JsonDeserializer<?> deser);
    public void addDeserializers(Map<Class<?>, JsonDeserializer<?>> deserializers);
    
    // Lookup implementation
    public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc);
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc);
    public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, DeserializationConfig config, BeanDescription beanDesc);
}

KeyDeserializers

Interface for registering custom key deserializers for maps.

public interface KeyDeserializers {
    // Key deserializer lookup
    KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException;
}

public class SimpleKeyDeserializers implements KeyDeserializers, Serializable {
    // Map-based key deserializer storage
    public SimpleKeyDeserializers();
    
    // Registration
    public SimpleKeyDeserializers addDeserializer(Class<?> type, KeyDeserializer deser);
    
    // Lookup implementation
    public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc);
}

ValueInstantiators

Interface for registering custom value instantiators.

public interface ValueInstantiators {
    // Value instantiator lookup
    ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator);
}

public class SimpleValueInstantiators implements ValueInstantiators, Serializable {
    // Map-based instantiator storage
    public SimpleValueInstantiators();
    
    // Registration
    public SimpleValueInstantiators addValueInstantiator(Class<?> type, ValueInstantiator inst);
    
    // Lookup implementation
    public ValueInstantiator findValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator);
}

Abstract Type Resolution

AbstractTypeResolver

Interface for resolving abstract types to concrete implementations.

public abstract class AbstractTypeResolver {
    // Type resolution
    public abstract JavaType findTypeMapping(DeserializationConfig config, JavaType type) throws JsonMappingException;
    public abstract JavaType resolveAbstractType(DeserializationConfig config, BeanDescription typeDesc) throws JsonMappingException;
}

public class SimpleAbstractTypeResolver extends AbstractTypeResolver {
    // Map-based type mapping storage
    public SimpleAbstractTypeResolver();
    
    // Mapping registration
    public <T> SimpleAbstractTypeResolver addMapping(Class<T> superType, Class<? extends T> subType);
    
    // Resolution implementation
    public JavaType findTypeMapping(DeserializationConfig config, JavaType type);
    public JavaType resolveAbstractType(DeserializationConfig config, BeanDescription typeDesc);
}

Usage Examples

Basic Custom Module

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.module.SimpleModule;

// Create a simple module for custom types
public class CustomTypesModule extends SimpleModule {
    
    public CustomTypesModule() {
        super("CustomTypesModule", Version.unknownVersion());
        
        // Add custom serializers
        addSerializer(Money.class, new MoneySerializer());
        addSerializer(PhoneNumber.class, new PhoneNumberSerializer());
        
        // Add custom deserializers
        addDeserializer(Money.class, new MoneyDeserializer());
        addDeserializer(PhoneNumber.class, new PhoneNumberDeserializer());
        
        // Add key deserializers
        addKeyDeserializer(Money.class, new MoneyKeyDeserializer());
        
        // Abstract type mappings
        addAbstractTypeMapping(Payment.class, CreditCardPayment.class);
    }
}

// Money serializer
public class MoneySerializer extends StdSerializer<Money> {
    public MoneySerializer() {
        super(Money.class);
    }
    
    @Override
    public void serialize(Money money, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("currency", money.getCurrency());
        gen.writeNumberField("amount", money.getAmount());
        gen.writeEndObject();
    }
}

// Money deserializer  
public class MoneyDeserializer extends StdDeserializer<Money> {
    public MoneyDeserializer() {
        super(Money.class);
    }
    
    @Override
    public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        String currency = node.get("currency").asText();
        BigDecimal amount = new BigDecimal(node.get("amount").asText());
        return new Money(currency, amount);
    }
}

// Usage
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new CustomTypesModule());

Money money = new Money("USD", new BigDecimal("99.99"));
String json = mapper.writeValueAsString(money);
Money parsed = mapper.readValue(json, Money.class);

Advanced Module with Multiple Components

public class EnhancedValidationModule extends SimpleModule {
    
    public EnhancedValidationModule() {
        super("EnhancedValidationModule", new Version(1, 0, 0, null, "com.example", "validation"));
        
        // Bean deserializer modifier for validation
        setDeserializerModifier(new ValidationBeanDeserializerModifier());
        
        // Custom annotation introspector
        insertAnnotationIntrospector(new ValidationAnnotationIntrospector());
        
        // Problem handler for validation errors
        addDeserializationProblemHandler(new ValidationProblemHandler());
        
        // Custom value instantiator for validated objects
        addValueInstantiator(ValidatedObject.class, new ValidatedObjectInstantiator());
    }
    
    // Custom bean deserializer modifier that adds validation
    private static class ValidationBeanDeserializerModifier extends BeanDeserializerModifier {
        
        @Override
        public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
            // Wrap deserializer with validation if class has validation annotations
            if (hasValidationAnnotations(beanDesc.getBeanClass())) {
                return new ValidatingDeserializer(deserializer);
            }
            return deserializer;
        }
        
        private boolean hasValidationAnnotations(Class<?> beanClass) {
            // Check for validation annotations
            return beanClass.isAnnotationPresent(Validated.class) || 
                   Arrays.stream(beanClass.getDeclaredFields())
                         .anyMatch(field -> field.isAnnotationPresent(NotNull.class) || 
                                           field.isAnnotationPresent(NotEmpty.class));
        }
    }
    
    // Validating deserializer wrapper
    private static class ValidatingDeserializer extends DelegatingDeserializer {
        
        protected ValidatingDeserializer(JsonDeserializer<?> delegatee) {
            super(delegatee);
        }
        
        @Override
        protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegatee) {
            return new ValidatingDeserializer(newDelegatee);
        }
        
        @Override
        public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            Object result = _delegatee.deserialize(p, ctxt);
            
            // Perform validation
            List<String> errors = validateObject(result);
            if (!errors.isEmpty()) {
                throw new JsonMappingException(p, "Validation failed: " + String.join(", ", errors));
            }
            
            return result;
        }
        
        private List<String> validateObject(Object obj) {
            List<String> errors = new ArrayList<>();
            Class<?> clazz = obj.getClass();
            
            // Simple validation logic
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                
                try {
                    Object value = field.get(obj);
                    
                    if (field.isAnnotationPresent(NotNull.class) && value == null) {
                        errors.add(field.getName() + " cannot be null");
                    }
                    
                    if (field.isAnnotationPresent(NotEmpty.class)) {
                        if (value == null || 
                            (value instanceof String && ((String) value).isEmpty()) ||
                            (value instanceof Collection && ((Collection<?>) value).isEmpty())) {
                            errors.add(field.getName() + " cannot be empty");
                        }
                    }
                } catch (IllegalAccessException e) {
                    // Handle reflection errors
                }
            }
            
            return errors;
        }
    }
}

// Custom annotations for validation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Validated {
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotNull {
}

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)
public @interface NotEmpty {
}

// Usage
@Validated
public class User {
    @NotNull
    private String username;
    
    @NotEmpty
    private String email;
    
    private String displayName; // Optional
    
    // constructors, getters, setters
}

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new EnhancedValidationModule());

// This will throw validation error for missing required fields
String invalidJson = "{\"displayName\":\"John\"}";
try {
    User user = mapper.readValue(invalidJson, User.class);
} catch (JsonMappingException e) {
    System.out.println("Validation failed: " + e.getMessage());
}

Conditional Module Registration

public class ConditionalModule extends SimpleModule {
    
    public ConditionalModule() {
        super("ConditionalModule");
    }
    
    @Override
    public void setupModule(SetupContext context) {
        DeserializationConfig deserConfig = context.getDeserializationConfig();
        SerializationConfig serConfig = context.getSerializationConfig();
        
        // Only add certain serializers based on configuration
        if (serConfig.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
            context.addSerializers(new PrettySerializers());
        }
        
        // Add different deserializers based on features
        if (deserConfig.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
            context.addDeserializers(new StrictDeserializers());
        } else {
            context.addDeserializers(new LenientDeserializers());
        }
        
        // Version-based conditional registration
        Version mapperVersion = context.getMapperVersion();
        if (mapperVersion.getMajorVersion() >= 2 && mapperVersion.getMinorVersion() >= 15) {
            context.addTypeModifier(new NewTypeModifier());
        }
    }
    
    private static class PrettySerializers extends Serializers.Base {
        @Override
        public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) {
            if (type.getRawClass() == ComplexObject.class) {
                return new PrettyComplexObjectSerializer();
            }
            return null;
        }
    }
}

Module Discovery and Auto-Registration

// Create a module finder utility
public class ModuleDiscovery {
    
    public static List<Module> findModules() {
        List<Module> modules = new ArrayList<>();
        
        // Look for modules in classpath
        ServiceLoader<Module> loader = ServiceLoader.load(Module.class);
        for (Module module : loader) {
            modules.add(module);
        }
        
        // Add specific known modules
        if (isClassAvailable("java.time.LocalDate")) {
            modules.add(new JavaTimeModule());
        }
        
        if (isClassAvailable("org.joda.time.DateTime")) {
            modules.add(new JodaModule());  
        }
        
        return modules;
    }
    
    private static boolean isClassAvailable(String className) {
        try {
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
    
    public static ObjectMapper createConfiguredMapper() {
        ObjectMapper mapper = new ObjectMapper();
        
        // Auto-register discovered modules
        List<Module> modules = findModules();
        mapper.registerModules(modules);
        
        return mapper;
    }
}

// Usage
ObjectMapper mapper = ModuleDiscovery.createConfiguredMapper();

Multi-Format Module

// Module that adds support for multiple formats
public class MultiFormatModule extends SimpleModule {
    
    public MultiFormatModule() {
        super("MultiFormatModule");
        
        // Date format support
        addSerializer(Date.class, new FlexibleDateSerializer());
        addDeserializer(Date.class, new FlexibleDateDeserializer());
        
        // Number format support
        addSerializer(BigDecimal.class, new ContextualBigDecimalSerializer());
        addDeserializer(BigDecimal.class, new ContextualBigDecimalDeserializer());
    }
    
    // Date serializer that adapts to context
    private static class FlexibleDateSerializer extends StdSerializer<Date> implements ContextualSerializer {
        private final DateFormat dateFormat;
        
        public FlexibleDateSerializer() {
            this(null);
        }
        
        private FlexibleDateSerializer(DateFormat dateFormat) {
            super(Date.class);
            this.dateFormat = dateFormat;
        }
        
        @Override
        public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
            if (property != null) {
                JsonFormat.Value format = prov.getAnnotationIntrospector().findFormat(property.getMember());
                if (format != null && format.hasPattern()) {
                    return new FlexibleDateSerializer(new SimpleDateFormat(format.getPattern()));
                }
            }
            return this;
        }
        
        @Override
        public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (dateFormat != null) {
                gen.writeString(dateFormat.format(value));
            } else {
                // Use timestamp or default format based on configuration
                if (serializers.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) {
                    gen.writeNumber(value.getTime());
                } else {
                    gen.writeString(value.toString());
                }
            }
        }
    }
}

Module Testing Utilities

// Utility class for testing modules
public class ModuleTestUtils {
    
    public static void testModuleRegistration(Module module) {
        ObjectMapper mapper = new ObjectMapper();
        
        // Test module registration
        mapper.registerModule(module);
        
        // Verify module is registered  
        Set<Object> moduleIds = mapper.getRegisteredModuleIds();
        boolean found = moduleIds.stream()
            .anyMatch(id -> id.equals(module.getTypeId()) || 
                          id.toString().contains(module.getModuleName()));
        
        if (!found) {
            throw new IllegalStateException("Module not properly registered: " + module.getModuleName());
        }
        
        System.out.println("Module registered successfully: " + module.getModuleName());
    }
    
    public static void testSerializationRoundTrip(Module module, Object testObject, Class<?> type) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(module);
        
        try {
            // Serialize
            String json = mapper.writeValueAsString(testObject);
            System.out.println("Serialized: " + json);
            
            // Deserialize
            Object result = mapper.readValue(json, type);
            
            // Basic equality check
            if (!testObject.equals(result)) {
                System.out.println("Warning: Serialization round-trip changed object");
                System.out.println("Original: " + testObject);
                System.out.println("Result: " + result);
            } else {
                System.out.println("Round-trip test passed for " + type.getSimpleName());
            }
            
        } catch (Exception e) {
            throw new RuntimeException("Round-trip test failed for " + type.getSimpleName(), e);
        }
    }
}

// Usage in tests
@Test
public void testCustomModule() {
    CustomTypesModule module = new CustomTypesModule();
    ModuleTestUtils.testModuleRegistration(module);
    
    Money testMoney = new Money("USD", new BigDecimal("123.45"));
    ModuleTestUtils.testSerializationRoundTrip(module, testMoney, Money.class);
}

Types

// Module finder utilities
public class JacksonModules {
    public static List<Module> findModules();
    public static List<Module> findModules(ClassLoader classLoader);
    public static void registerWellKnownModules(ObjectMapper mapper);
}

// Version information for modules
public class Version implements Comparable<Version>, Serializable {
    public Version(int major, int minor, int patchLevel, String snapshotInfo, String groupId, String artifactId);
    
    public int getMajorVersion();
    public int getMinorVersion(); 
    public int getPatchLevel();
    public String getGroupId();
    public String getArtifactId();
    public boolean isSnapshot();
    public boolean isUnknownVersion();
    
    public static Version unknownVersion();
    
    public String toString();
    public int compareTo(Version other);
}

// Versioned interface for components
public interface Versioned {
    Version version();
}

// Delegating deserializer base class
public abstract class DelegatingDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer, ResolvableDeserializer {
    protected final JsonDeserializer<?> _delegatee;
    
    protected DelegatingDeserializer(JsonDeserializer<?> delegatee);
    
    protected abstract JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegatee);
    
    public JsonDeserializer<?> getDelegatee();
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException;
    public Object deserialize(JsonParser p, DeserializationContext ctxt, Object intoValue) throws IOException;
    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException;
    
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException;
    public void resolve(DeserializationContext ctxt) throws JsonMappingException;
}

// Delegating serializer base class
public abstract class DelegatingSerializer extends JsonSerializer<Object> implements ContextualSerializer, ResolvableSerializer {
    protected final JsonSerializer<Object> _delegatee;
    
    protected DelegatingSerializer(JsonSerializer<?> delegatee);
    
    protected abstract JsonSerializer<?> newDelegatingInstance(JsonSerializer<?> newDelegatee);
    
    public JsonSerializer<?> getDelegatee();
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException;
    public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException;
    
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException;
    public void resolve(SerializerProvider provider) throws JsonMappingException;
}

// Named type for subtype registration
public class NamedType implements Serializable {
    public NamedType(Class<?> c);
    public NamedType(Class<?> c, String name);
    
    public Class<?> getType();
    public String getName();
    public boolean hasName();
    
    public boolean equals(Object o);
    public int hashCode();
    public String toString();
}

Install with Tessl CLI

npx tessl i tessl/maven-com-fasterxml-jackson-core--jackson-databind

docs

advanced-features.md

annotations.md

configuration.md

deserialization.md

index.md

json-tree-model.md

modules.md

object-mapping.md

serialization.md

type-system.md

tile.json