下面列出了怎么用com.fasterxml.jackson.databind.type.ClassKey的API类实例代码及写法,或者点击链接到github查看源代码。
@BeforeEach
void init() throws IllegalAccessException {
Field convertersField2 = FieldUtils.getDeclaredField(ObjectMapper.class, "_mixIns", true);
SimpleMixInResolver _mixIns = (SimpleMixInResolver) convertersField2.get(Json.mapper());
Field convertersField3 = FieldUtils.getDeclaredField(SimpleMixInResolver.class, "_localMixIns", true);
Map<ClassKey, Class<?>> _localMixIns = (Map<ClassKey, Class<?>>) convertersField3.get(_mixIns);
Iterator<Map.Entry<ClassKey, Class<?>>> it = _localMixIns.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<ClassKey, Class<?>> entry = it.next();
if (entry.getKey().toString().startsWith("org.springframework")) {
springMixins.put(entry.getKey(), entry.getValue());
it.remove();
}
}
}
public <T> SlotPropertyReader slotReaderFor(Class<T> slotClass) {
return this.slotReaderCache.computeIfAbsent(new ClassKey(slotClass), k -> {
com.amazon.ask.interaction.annotation.data.SlotPropertyReader slotPropertyReader = Utils.findAnnotation(slotClass, com.amazon.ask.interaction.annotation.data.SlotPropertyReader.class);
if (slotPropertyReader != null) {
return Utils.instantiate(slotPropertyReader.value());
}
if (slotClass.isEnum()) {
return new EnumCustomSlotReader(slotClass);
}
ClassKey classKey = new ClassKey(slotClass);
if (this.slotPropertyReaders.containsKey(classKey)) {
return this.slotPropertyReaders.get(classKey);
}
TypeReflector<?> slotTypeReflector = new TypeReflector<>(slotClass);
Map<String, SlotPropertyReader> readers = new HashMap<>();
for (PropertyDescriptor slotProperty : slotTypeReflector.getPropertyDescriptors()) {
if (slotTypeReflector.getAnnotation(slotProperty, AlexaIgnore.class) != null) {
continue;
}
readers.put(slotProperty.getName(), resolveSlotPropertyReader(slotTypeReflector, slotProperty));
}
return new ReflectiveSlotReader(slotTypeReflector, readers);
});
}
protected SlotPropertyReader resolveSlotPropertyReader(TypeReflector<?> slotTypeReflector, PropertyDescriptor slotProperty) {
Class<?> propertyType = slotProperty.getPropertyType();
if (propertyType == Object.class) {
propertyType = slotTypeReflector.reifyPropertyType(slotProperty);
}
SlotPropertyReader reader;
com.amazon.ask.interaction.annotation.data.SlotPropertyReader attribute = slotTypeReflector.getAnnotation(slotProperty, com.amazon.ask.interaction.annotation.data.SlotPropertyReader.class);
if (attribute == null) {
attribute = Utils.findAnnotation(propertyType, com.amazon.ask.interaction.annotation.data.SlotPropertyReader.class);
}
if (attribute != null) {
return Utils.instantiate(attribute.value());
} else {
reader = slotPropertyReaders.get(new ClassKey(propertyType));
}
if (reader == null) {
throw new IllegalArgumentException(String.format("Could not resolve a %s for %s", SlotPropertyReader.class.getName(), propertyType.getName()));
}
return reader;
}
protected void _addSerializer(Class<?> cls, JsonSerializer<?> ser)
{
ClassKey key = new ClassKey(cls);
// Interface or class type?
if (cls.isInterface()) {
if (_interfaceMappings == null) {
_interfaceMappings = new HashMap<ClassKey,JsonSerializer<?>>();
}
_interfaceMappings.put(key, ser);
} else { // nope, class:
if (_classMappings == null) {
_classMappings = new HashMap<ClassKey,JsonSerializer<?>>();
}
_classMappings.put(key, ser);
if (cls == Enum.class) {
_hasEnumSerializer = true;
}
}
}
/**
* Method for adding a mapping from super type to specific subtype.
* Arguments will be checked by method, to ensure that <code>superType</code>
* is abstract (since resolver is never called for concrete classes);
* as well as to ensure that there is supertype/subtype relationship
* (to ensure there won't be cycles during resolution).
*
* @param superType Abstract type to resolve
* @param subType Sub-class of superType, to map superTo to
*
* @return This resolver, to allow chaining of initializations
*/
public <T> SimpleAbstractTypeResolver addMapping(Class<T> superType, Class<? extends T> subType)
{
// Sanity checks, just in case someone tries to force typing...
if (superType == subType) {
throw new IllegalArgumentException("Cannot add mapping from class to itself");
}
if (!superType.isAssignableFrom(subType)) {
throw new IllegalArgumentException("Cannot add mapping from class "+superType.getName()
+" to "+subType.getName()+", as latter is not a subtype of former");
}
if (!Modifier.isAbstract(superType.getModifiers())) {
throw new IllegalArgumentException("Cannot add mapping from class "+superType.getName()
+" since it is not abstract");
}
_mappings.put(new ClassKey(superType), subType);
return this;
}
public PropertyName findRootName(Class<?> rootType, MapperConfig<?> config)
{
ClassKey key = new ClassKey(rootType);
PropertyName name = _rootNames.get(key);
if (name != null) {
return name;
}
BeanDescription beanDesc = config.introspectClassAnnotations(rootType);
AnnotationIntrospector intr = config.getAnnotationIntrospector();
AnnotatedClass ac = beanDesc.getClassInfo();
name = intr.findRootName(ac);
// No answer so far? Let's just default to using simple class name
if (name == null || !name.hasSimpleName()) {
// Should we strip out enclosing class tho? For now, nope:
name = PropertyName.construct(rootType.getSimpleName());
}
_rootNames.put(key, name);
return name;
}
@AfterEach
private void clean() throws IllegalAccessException {
Field convertersField2 = FieldUtils.getDeclaredField(ObjectMapper.class, "_mixIns", true);
SimpleMixInResolver _mixIns = (SimpleMixInResolver) convertersField2.get(Json.mapper());
Field convertersField3 = FieldUtils.getDeclaredField(SimpleMixInResolver.class, "_localMixIns", true);
Map<ClassKey, Class<?>> _localMixIns = (Map<ClassKey, Class<?>>) convertersField3.get(_mixIns);
_localMixIns.putAll(springMixins);
}
protected IntentMapper(Model model,
Map<ClassKey, IntentPropertyReader> intentPropertyReaders,
Map<ClassKey, SlotPropertyReader> slotPropertyReaders) {
this.model = assertNotNull(model, "model");
this.intentPropertyReaders = Collections.unmodifiableMap(assertNotNull(intentPropertyReaders, "intentPropertyReaders"));
this.slotPropertyReaders = Collections.unmodifiableMap(assertNotNull(slotPropertyReaders, "slotPropertyReaders"));
this.intentReaderCache = new ConcurrentHashMap<>();
this.slotReaderCache = new ConcurrentHashMap<>();
}
public Builder addIntentPropertyReader(ClassKey classKey, IntentPropertyReader intentPropertyReader) {
if (this.intentPropertyReaders == null) {
this.intentPropertyReaders = new HashMap<>();
}
this.intentPropertyReaders.put(classKey, intentPropertyReader);
return this;
}
public Builder addSlotPropertyReader(ClassKey classKey, SlotPropertyReader slotPropertyReader) {
if (this.slotPropertyReaders == null) {
this.slotPropertyReaders = new HashMap<>();
}
this.slotPropertyReaders.put(classKey, slotPropertyReader);
return this;
}
protected JsonSerializer<?> _findInterfaceMapping(Class<?> cls, ClassKey key)
{
for (Class<?> iface : cls.getInterfaces()) {
key.reset(iface);
JsonSerializer<?> ser = _interfaceMappings.get(key);
if (ser != null) {
return ser;
}
ser = _findInterfaceMapping(iface, key);
if (ser != null) {
return ser;
}
}
return null;
}
public SimpleKeyDeserializers addDeserializer(Class<?> forClass, KeyDeserializer deser)
{
if (_classMappings == null) {
_classMappings = new HashMap<ClassKey,KeyDeserializer>();
}
_classMappings.put(new ClassKey(forClass), deser);
return this;
}
@Override
public KeyDeserializer findKeyDeserializer(JavaType type,
DeserializationConfig config, BeanDescription beanDesc)
{
if (_classMappings == null) {
return null;
}
return _classMappings.get(new ClassKey(type.getRawClass()));
}
@Override
public ValueInstantiator findValueInstantiator(DeserializationConfig config,
BeanDescription beanDesc, ValueInstantiator defaultInstantiator)
{
ValueInstantiator inst = _classMappings.get(new ClassKey(beanDesc.getBeanClass()));
return (inst == null) ? defaultInstantiator : inst;
}
@Override
public JavaType findTypeMapping(DeserializationConfig config, JavaType type)
{
// this is the main mapping base, so let's
Class<?> src = type.getRawClass();
Class<?> dst = _mappings.get(new ClassKey(src));
if (dst == null) {
return null;
}
// 09-Aug-2015, tatu: Instead of direct call via JavaType, better use TypeFactory
return config.getTypeFactory().constructSpecializedType(type, dst);
}
public void setLocalDefinitions(Map<Class<?>, Class<?>> sourceMixins) {
if (sourceMixins == null || sourceMixins.isEmpty()) {
_localMixIns = null;
} else {
Map<ClassKey,Class<?>> mixIns = new HashMap<ClassKey,Class<?>>(sourceMixins.size());
for (Map.Entry<Class<?>,Class<?>> en : sourceMixins.entrySet()) {
mixIns.put(new ClassKey(en.getKey()), en.getValue());
}
_localMixIns = mixIns;
}
}
@Override
public SimpleMixInResolver copy() {
ClassIntrospector.MixInResolver overrides = (_overrides == null)
? null : _overrides.copy();
Map<ClassKey,Class<?>> mixIns = (_localMixIns == null)
? null : new HashMap<ClassKey,Class<?>>(_localMixIns);
return new SimpleMixInResolver(overrides, mixIns);
}
@Override
public Class<?> findMixInClassFor(Class<?> cls)
{
Class<?> mixin = (_overrides == null) ? null : _overrides.findMixInClassFor(cls);
if (mixin == null && (_localMixIns != null)) {
mixin = _localMixIns.get(new ClassKey(cls));
}
return mixin;
}
/**
* Helper method called to (try to) locate deserializer for given sub-type of
* type that this deserializer handles.
*/
protected JsonDeserializer<Object> _findSubclassDeserializer(DeserializationContext ctxt,
Object bean, TokenBuffer unknownTokens)
throws IOException
{
JsonDeserializer<Object> subDeser;
// First: maybe we have already created sub-type deserializer?
synchronized (this) {
subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass()));
}
if (subDeser != null) {
return subDeser;
}
// If not, maybe we can locate one. First, need provider
JavaType type = ctxt.constructType(bean.getClass());
/* 30-Jan-2012, tatu: Ideally we would be passing referring
* property; which in theory we could keep track of via
* ResolvableDeserializer (if we absolutely must...).
* But for now, let's not bother.
*/
// subDeser = ctxt.findValueDeserializer(type, _property);
subDeser = ctxt.findRootValueDeserializer(type);
// Also, need to cache it
if (subDeser != null) {
synchronized (this) {
if (_subDeserializers == null) {
_subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
}
_subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
}
}
return subDeser;
}
public <T> IntentReader<T> intentReaderFor(JavaType type) {
return (IntentReader<T>) intentReaderCache.computeIfAbsent(type, k -> {
TypeReflector<T> reflector = new TypeReflector<>(type);
Map<String, IntentPropertyReader<?>> intentPropertyReaders = new HashMap<>();
Set<String> slotNames = new HashSet<>(); // detect duplicate slot names
for (PropertyDescriptor prop : reflector.getPropertyDescriptors()) {
if (reflector.getAnnotation(prop, AlexaIgnore.class) != null) {
continue;
}
Class<?> propertyType = prop.getPropertyType() != Object.class
? prop.getPropertyType()
: reflector.reifyPropertyType(prop);
IntentPropertyReader reader;
com.amazon.ask.interaction.annotation.data.IntentPropertyReader intentPropertyReader = reflector.getAnnotation(prop, com.amazon.ask.interaction.annotation.data.IntentPropertyReader.class);
if (intentPropertyReader == null) {
intentPropertyReader = Utils.findAnnotation(propertyType, com.amazon.ask.interaction.annotation.data.IntentPropertyReader.class);
}
if (intentPropertyReader != null) {
reader = Utils.instantiate(intentPropertyReader.value());
} else {
// TODO: Should we check this before the type's annotation?
reader = this.intentPropertyReaders.get(new ClassKey(propertyType));
}
// Slot properties must be annotated with @AlexaSlot
SlotProperty slotProperty = reflector.getAnnotation(prop, SlotProperty.class);
if (slotProperty != null) {
String slotName = slotProperty.name().isEmpty() ? prop.getName() : slotProperty.name();
if (slotNames.contains(slotName)) {
throw new IllegalArgumentException(String.format("Slot '%s' declared multiple times on intent %s", slotName, type.getRawClass().getName()));
}
slotNames.add(slotName);
if (reader == null) {
SlotPropertyReader slotPropertyReader;
com.amazon.ask.interaction.annotation.data.SlotPropertyReader alexaSlotPropertyReader = reflector.getAnnotation(prop, com.amazon.ask.interaction.annotation.data.SlotPropertyReader.class);
if (alexaSlotPropertyReader != null) {
slotPropertyReader = Utils.instantiate(alexaSlotPropertyReader.value());
} else {
slotPropertyReader = slotReaderFor(propertyType);
}
reader = new IntentSlotPropertyReader(slotPropertyReader,slotName);
}
}
if (reader == null) {
throw new IllegalArgumentException(String.format("Could not resolve an %s for property '%s' on intent %s", IntentPropertyReader.class.getName(), prop.getName(), type.getRawClass().getName()));
}
intentPropertyReaders.put(prop.getName(), reader);
}
return new ReflectiveIntentReader<T>(reflector, intentPropertyReaders);
});
}
public Builder withIntentPropertyReaders(Map<ClassKey, IntentPropertyReader> intentPropertyReaders) {
this.intentPropertyReaders = intentPropertyReaders;
return this;
}
public Builder addIntentPropertyReaders(Map<ClassKey, IntentPropertyReader> intentPropertyReaders) {
intentPropertyReaders.forEach(this::addIntentPropertyReader);
return this;
}
public Builder addIntentPropertyReader(Class<?> clazz, IntentPropertyReader intentPropertyReader) {
return addIntentPropertyReader(new ClassKey(clazz), intentPropertyReader);
}
public Builder withSlotPropertyReaders(Map<ClassKey, SlotPropertyReader> slotPropertyReaders) {
this.slotPropertyReaders = slotPropertyReaders;
return this;
}
public Builder addSlotPropertyReaders(Map<ClassKey, SlotPropertyReader> slotPropertyReaders) {
slotPropertyReaders.forEach(this::addSlotPropertyReader);
return this;
}
public Builder addSlotPropertyReader(Class<?> slotClass, SlotPropertyReader slotPropertyReader) {
return addSlotPropertyReader(new ClassKey(slotClass), slotPropertyReader);
}
@Override
public JsonSerializer<?> findSerializer(SerializationConfig config,
JavaType type, BeanDescription beanDesc)
{
Class<?> cls = type.getRawClass();
ClassKey key = new ClassKey(cls);
JsonSerializer<?> ser = null;
// First: direct match?
if (cls.isInterface()) {
if (_interfaceMappings != null) {
ser = _interfaceMappings.get(key);
if (ser != null) {
return ser;
}
}
} else {
if (_classMappings != null) {
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
// [Issue#227]: Handle registration of plain `Enum` serializer
if (_hasEnumSerializer && type.isEnumType()) {
key.reset(Enum.class);
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
}
// If not direct match, maybe super-class match?
for (Class<?> curr = cls; (curr != null); curr = curr.getSuperclass()) {
key.reset(curr);
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
}
}
}
// No direct match? How about super-interfaces?
if (_interfaceMappings != null) {
ser = _findInterfaceMapping(cls, key);
if (ser != null) {
return ser;
}
// still no matches? Maybe interfaces of super classes
if (!cls.isInterface()) {
while ((cls = cls.getSuperclass()) != null) {
ser = _findInterfaceMapping(cls, key);
if (ser != null) {
return ser;
}
}
}
}
return null;
}
public SimpleValueInstantiators()
{
_classMappings = new HashMap<ClassKey,ValueInstantiator>();
}
public SimpleValueInstantiators addValueInstantiator(Class<?> forType,
ValueInstantiator inst)
{
_classMappings.put(new ClassKey(forType), inst);
return this;
}
protected SimpleMixInResolver(ClassIntrospector.MixInResolver overrides,
Map<ClassKey,Class<?>> mixins) {
_overrides = overrides;
_localMixIns = mixins;
}