/**
   * 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);
  }
示例#2
0
  /**
   * 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;
 }