/** * Method called to construct fallback {@link SettableAnyProperty} for handling unknown bean * properties, given a method that has been designated as such setter. */ protected SettableAnyProperty constructAnySetter( DeserializationContext ctxt, BeanDescription beanDesc, AnnotatedMethod setter) throws JsonMappingException { if (ctxt.canOverrideAccessModifiers()) { setter.fixAccess(); // to ensure we can call it } // we know it's a 2-arg method, second arg is the value JavaType type = beanDesc.bindingsForBeanType().resolveType(setter.getGenericParameterType(1)); BeanProperty.Std property = new BeanProperty.Std(setter.getName(), type, beanDesc.getClassAnnotations(), setter); type = resolveType(ctxt, beanDesc, type, setter); /* AnySetter can be annotated with @JsonClass (etc) just like a * regular setter... so let's see if those are used. * Returns null if no annotations, in which case binding will * be done at a later point. */ JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, setter); if (deser != null) { return new SettableAnyProperty(property, setter, type, deser); } /* Otherwise, method may specify more specific (sub-)class for * value (no need to check if explicit deser was specified): */ type = modifyTypeByAnnotation(ctxt, setter, type); return new SettableAnyProperty(property, setter, type, null); }
/** * Method for resolving member method information: aggregating all non-static methods and * combining annotations (to implement method-annotation inheritance) * * @param collectIgnored Whether to collect list of ignored methods for later retrieval */ public void resolveMemberMethods(MethodFilter methodFilter, boolean collectIgnored) { _memberMethods = new AnnotatedMethodMap(); AnnotatedMethodMap mixins = new AnnotatedMethodMap(); // first: methods from the class itself _addMemberMethods(_class, methodFilter, _memberMethods, _primaryMixIn, mixins); // and then augment these with annotations from super-types: for (Class<?> cls : _superTypes) { Class<?> mixin = (_mixInResolver == null) ? null : _mixInResolver.findMixInClassFor(cls); _addMemberMethods(cls, methodFilter, _memberMethods, mixin, mixins); } // Special case: mix-ins for Object.class? (to apply to ALL classes) if (_mixInResolver != null) { Class<?> mixin = _mixInResolver.findMixInClassFor(Object.class); if (mixin != null) { _addMethodMixIns(methodFilter, _memberMethods, mixin, mixins); } } /* Any unmatched mix-ins? Most likely error cases (not matching * any method); but there is one possible real use case: * exposing Object#hashCode (alas, Object#getClass can NOT be * exposed, see [JACKSON-140]) */ if (!mixins.isEmpty()) { Iterator<AnnotatedMethod> it = mixins.iterator(); while (it.hasNext()) { AnnotatedMethod mixIn = it.next(); try { Method m = Object.class.getDeclaredMethod(mixIn.getName(), mixIn.getParameterClasses()); if (m != null) { AnnotatedMethod am = _constructMethod(m); _addMixOvers(mixIn.getAnnotated(), am, false); _memberMethods.add(am); } } catch (Exception e) { } } } /* And last but not least: let's remove all methods that are * deemed to be ignorable after all annotations have been * properly collapsed. */ Iterator<AnnotatedMethod> it = _memberMethods.iterator(); while (it.hasNext()) { AnnotatedMethod am = it.next(); if (_annotationIntrospector.isIgnorableMethod(am)) { it.remove(); if (collectIgnored) { _ignoredMethods = ArrayBuilders.addToList(_ignoredMethods, am); } } } }
/** * Method used to locate the method of introspected class that implements {@link * sh.calaba.org.codehaus.jackson.annotate.JsonAnyGetter}. If no such method exists null is * returned. If more than one are found, an exception is thrown. * * @since 1.6 */ @Override public AnnotatedMethod findAnyGetter() throws IllegalArgumentException { if (_anyGetterMethod != null) { /* For now let's require a Map; in future can add support for other * types like perhaps Iterable<Map.Entry>? */ Class<?> type = _anyGetterMethod.getRawType(); if (!Map.class.isAssignableFrom(type)) { throw new IllegalArgumentException( "Invalid 'any-getter' annotation on method " + _anyGetterMethod.getName() + "(): return type is not instance of java.util.Map"); } } return _anyGetterMethod; }
protected boolean isFactoryMethod(AnnotatedMethod am) { /* First: return type must be compatible with the introspected class * (i.e. allowed to be sub-class, although usually is the same * class) */ Class<?> rt = am.getRawType(); if (!getBeanClass().isAssignableFrom(rt)) { return false; } /* Also: must be a recognized factory method, meaning: * (a) marked with @JsonCreator annotation, or * (a) "valueOf" (at this point, need not be public) */ if (_annotationIntrospector.hasCreatorAnnotation(am)) { return true; } if ("valueOf".equals(am.getName())) { return true; } return false; }
/** * Method used to locate the method of introspected class that implements {@link * sh.calaba.org.codehaus.jackson.annotate.JsonAnySetter}. If no such method exists null is * returned. If more than one are found, an exception is thrown. Additional checks are also made * to see that method signature is acceptable: needs to take 2 arguments, first one String or * Object; second any can be any type. */ @Override public AnnotatedMethod findAnySetter() throws IllegalArgumentException { if (_anySetterMethod != null) { /* Also, let's be somewhat strict on how field name is to be * passed; String, Object make sense, others not * so much. */ /* !!! 18-May-2009, tatu: how about enums? Can add support if * requested; easy enough for devs to add support within * method. */ Class<?> type = _anySetterMethod.getParameterClass(0); if (type != String.class && type != Object.class) { throw new IllegalArgumentException( "Invalid 'any-setter' annotation on method " + _anySetterMethod.getName() + "(): first argument not of type String or Object, but " + type.getName()); } } return _anySetterMethod; }