package com.fasterxml.jackson.dataformat.avro;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver;
import com.fasterxml.jackson.databind.type.TypeFactory;

TypeIdResolver for Avro type IDs embedded in schemas. Avro generally uses class names, but we want to also support named subtypes so that developers can easily remap the embedded type IDs to a different runtime class.
Since:2.9
/** * {@link com.fasterxml.jackson.databind.jsontype.TypeIdResolver} for Avro type IDs embedded in schemas. Avro generally uses class names, * but we want to also support named subtypes so that developers can easily remap the embedded type IDs to a different runtime class. * * @since 2.9 */
public class AvroTypeIdResolver extends ClassNameIdResolver { private final Map<String, Class<?>> _idTypes = new HashMap<>(); private final Map<Class<?>, String> _typeIds = new HashMap<>(); public AvroTypeIdResolver(JavaType baseType, TypeFactory typeFactory, PolymorphicTypeValidator ptv, Collection<NamedType> subTypes) { this(baseType, typeFactory, ptv); if (subTypes != null) { for (NamedType namedType : subTypes) { registerSubtype(namedType.getType(), namedType.getName()); } } } public AvroTypeIdResolver(JavaType baseType, TypeFactory typeFactory, PolymorphicTypeValidator ptv) { super(baseType, typeFactory, ptv); } @Override public void registerSubtype(Class<?> type, String name) { _idTypes.put(name, type); _typeIds.put(type, name); } @Override protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException { // base types don't have subclasses if (_baseType.isPrimitive()) { return _baseType; } // check if there's a specific type we should be using for this ID Class<?> subType = _idTypes.get(id); if (subType != null) { id = _idFrom(null, subType, _typeFactory); } try { return super._typeFromId(id, ctxt); } catch (InvalidTypeIdException | IllegalArgumentException e) { // AvroTypeDeserializer expects null if we can't map the type ID to a class; It will throw an appropriate error if we can't // find a usable type. return null; } } }