Jackson Data Binding Source Code

Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".

  • Jackson Data Binding module allows you to converts JSON to and from POJO (Plain Old Java Object) using property accessor or using annotations.
  • Jackson Databind Source Code files are provided in the source packge (jackson-databind-2.12.4-sources.jar). You can download it at Jackson Maven Website.

    You can also browse Jackson Databind Source Code below:

    ✍: FYIcenter.com

    com/fasterxml/jackson/databind/introspect/AnnotatedMethodCollector.java

    package com.fasterxml.jackson.databind.introspect;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.*;
    
    import com.fasterxml.jackson.databind.AnnotationIntrospector;
    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver;
    import com.fasterxml.jackson.databind.type.TypeFactory;
    import com.fasterxml.jackson.databind.util.ClassUtil;
    
    public class AnnotatedMethodCollector
        extends CollectorBase
    {
        private final MixInResolver _mixInResolver;
    
        /**
         * @since 2.11
         */
        private final boolean _collectAnnotations;
    
        AnnotatedMethodCollector(AnnotationIntrospector intr,
                MixInResolver mixins, boolean collectAnnotations)
        {
            super(intr);
            _mixInResolver = (intr == null) ? null : mixins;
            _collectAnnotations = collectAnnotations;
        }
    
        public static AnnotatedMethodMap collectMethods(AnnotationIntrospector intr,
                TypeResolutionContext tc,
                MixInResolver mixins, TypeFactory types,
                JavaType type, List<JavaType> superTypes, Class<?> primaryMixIn,
                boolean collectAnnotations)
        {
            // Constructor also always members of resolved class, parent == resolution context
            return new AnnotatedMethodCollector(intr, mixins, collectAnnotations)
                    .collect(types, tc, type, superTypes, primaryMixIn);
        }
    
        AnnotatedMethodMap collect(TypeFactory typeFactory, TypeResolutionContext tc,
                JavaType mainType, List<JavaType> superTypes, Class<?> primaryMixIn)
        {
            Map<MemberKey,MethodBuilder> methods = new LinkedHashMap<>();
            
            // first: methods from the class itself
            _addMemberMethods(tc, mainType.getRawClass(), methods, primaryMixIn);
    
            // and then augment these with annotations from super-types:
            for (JavaType type : superTypes) {
                Class<?> mixin = (_mixInResolver == null) ? null : _mixInResolver.findMixInClassFor(type.getRawClass());
                _addMemberMethods(
                        new TypeResolutionContext.Basic(typeFactory, type.getBindings()),
                        type.getRawClass(), methods, mixin);
            }
            // Special case: mix-ins for Object.class? (to apply to ALL classes)
            boolean checkJavaLangObject = false;
            if (_mixInResolver != null) {
                Class<?> mixin = _mixInResolver.findMixInClassFor(Object.class);
                if (mixin != null) {
                    _addMethodMixIns(tc, mainType.getRawClass(), methods, mixin); //, mixins);
                    checkJavaLangObject = true;
                }
            }
    
            // 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)
            // Since we only know of that ONE case, optimize for it
            if (checkJavaLangObject && (_intr != null) && !methods.isEmpty()) {
                // Could use lookup but probably as fast or faster to traverse
                for (Map.Entry<MemberKey,MethodBuilder> entry : methods.entrySet()) {
                    MemberKey k = entry.getKey();
                    if (!"hashCode".equals(k.getName()) || (0 != k.argCount())) {
                        continue;
                    }
                    try {
                        // And with that, we can generate it appropriately
                        Method m = Object.class.getDeclaredMethod(k.getName());
                        if (m != null) {
                            MethodBuilder b = entry.getValue();
                            b.annotations = collectDefaultAnnotations(b.annotations,
                                    m.getDeclaredAnnotations());
                            b.method = m;
                       }
                    } catch (Exception e) { }
                }
            }
    
            // And then let's create the lookup map
            if (methods.isEmpty()) {
                return new AnnotatedMethodMap();
            }
            Map<MemberKey,AnnotatedMethod> actual = new LinkedHashMap<>(methods.size());
            for (Map.Entry<MemberKey,MethodBuilder> entry : methods.entrySet()) {
                AnnotatedMethod am = entry.getValue().build();
                if (am != null) {
                    actual.put(entry.getKey(), am);
                }
            }
            return new AnnotatedMethodMap(actual);
        }
    
        private void _addMemberMethods(TypeResolutionContext tc,
                Class<?> cls, Map<MemberKey,MethodBuilder> methods, Class<?> mixInCls)
        {
            // first, mixIns, since they have higher priority then class methods
            if (mixInCls != null) {
                _addMethodMixIns(tc, cls, methods, mixInCls);
            }
            if (cls == null) { // just so caller need not check when passing super-class
                return;
            }
            // then methods from the class itself
            for (Method m : ClassUtil.getClassMethods(cls)) {
                if (!_isIncludableMemberMethod(m)) {
                    continue;
                }
                final MemberKey key = new MemberKey(m);
                MethodBuilder b = methods.get(key);
                if (b == null) {
                    AnnotationCollector c = (_intr == null) ? AnnotationCollector.emptyCollector()
                            : collectAnnotations(m.getDeclaredAnnotations());
                    methods.put(key, new MethodBuilder(tc, m, c));
                } else {
                    if (_collectAnnotations) {
                        b.annotations = collectDefaultAnnotations(b.annotations, m.getDeclaredAnnotations());
                    }
                    Method old = b.method;
                    if (old == null) { // had "mix-over", replace
                        b.method = m;
    //                } else if (old.getDeclaringClass().isInterface() && !m.getDeclaringClass().isInterface()) {
                    } else if (Modifier.isAbstract(old.getModifiers())
                            && !Modifier.isAbstract(m.getModifiers())) {
                        // 06-Jan-2010, tatu: Except that if method we saw first is
                        // from an interface, and we now find a non-interface definition, we should
                        //   use this method, but with combination of annotations.
                        //   This helps (or rather, is essential) with JAXB annotations and
                        //   may also result in faster method calls (interface calls are slightly
                        //   costlier than regular method calls)
                        b.method = m;
                        // 23-Aug-2017, tatu: [databind#1705] Also need to change the type resolution context if so
                        //    (note: mix-over case above shouldn't need it)
                        b.typeContext = tc;
                    }
                }
            }
        }
    
        protected void _addMethodMixIns(TypeResolutionContext tc, Class<?> targetClass,
                Map<MemberKey,MethodBuilder> methods, Class<?> mixInCls)
        {
            if (_intr == null) {
                return;
            }
            for (Class<?> mixin : ClassUtil.findRawSuperTypes(mixInCls, targetClass, true)) {
                for (Method m : mixin.getDeclaredMethods()) {
                    if (!_isIncludableMemberMethod(m)) {
                        continue;
                    }
                    final MemberKey key = new MemberKey(m);
                    MethodBuilder b = methods.get(key);
                    Annotation[] anns = m.getDeclaredAnnotations();
                    if (b == null) {
                        // nothing yet; add but do NOT specify method -- this marks it
                        // as "mix-over", floating mix-in
                        methods.put(key, new MethodBuilder(tc, null, collectAnnotations(anns)));
                    } else {
                        b.annotations = collectDefaultAnnotations(b.annotations, anns);
                    }
                }
            }
        }
    
        private static boolean _isIncludableMemberMethod(Method m)
        {
            if (Modifier.isStatic(m.getModifiers())
                    // Looks like generics can introduce hidden bridge and/or synthetic methods.
                    // I don't think we want to consider those...
                    || m.isSynthetic() || m.isBridge()) {
                return false;
            }
            // also, for now we have no use for methods with more than 2 arguments:
            // (2 argument methods for "any setter", fwtw)
            int pcount = m.getParameterTypes().length;
            return (pcount <= 2);
        }
    
        private final static class MethodBuilder {
            public TypeResolutionContext typeContext;
    
            // Method left empty for "floating" mix-in, filled in as need be
            public Method method;
            public AnnotationCollector annotations;
    
            public MethodBuilder(TypeResolutionContext tc, Method m,
                    AnnotationCollector ann) {
                typeContext = tc;
                method = m;
                annotations = ann;
            }
    
            public AnnotatedMethod build() {
                if (method == null) {
                    return null;
                }
                // 12-Apr-2017, tatu: Note that parameter annotations are NOT collected -- we could
                //   collect them if that'd make sense but...
                return new AnnotatedMethod(typeContext, method, annotations.asAnnotationMap(), null);
            }
        }
    }
    

    com/fasterxml/jackson/databind/introspect/AnnotatedMethodCollector.java

     

    ⇒ Jackson Annotations Source Code

    ⇐ Download and Install Jackson Binary Package

    ⇑ Downloading and Reviewing jackson-*.jar

    ⇑⇑ Jackson - Java JSON library

    2022-03-29, 32016👍, 0💬