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/MappingIterator.java

    package com.fasterxml.jackson.databind;
    
    import java.io.Closeable;
    import java.io.IOException;
    import java.util.*;
    
    import com.fasterxml.jackson.core.*;
    
    /**
     * Iterator exposed by {@link ObjectMapper} when binding sequence of
     * objects. Extension is done to allow more convenient exposing of
     * {@link IOException} (which basic {@link Iterator} does not expose)
     */
    public class MappingIterator<T> implements Iterator<T>, Closeable
    {
        protected final static MappingIterator<?> EMPTY_ITERATOR =
            new MappingIterator<Object>(null, null, null, null, false, null);
    
        /*
        /**********************************************************
        /* State constants
        /**********************************************************
         */
    
        /**
         * State in which iterator is closed
         */
        protected final static int STATE_CLOSED = 0;
        
        /**
         * State in which value read failed
         */
        protected final static int STATE_NEED_RESYNC = 1;
        
        /**
         * State in which no recovery is needed, but "hasNextValue()" needs
         * to be called first
         */
        protected final static int STATE_MAY_HAVE_VALUE = 2;
    
        /**
         * State in which "hasNextValue()" has been succesfully called
         * and deserializer can be called to fetch value
         */
        protected final static int STATE_HAS_VALUE = 3;
    
        /*
        /**********************************************************
        /* Configuration
        /**********************************************************
         */
    
        /**
         * Type to bind individual elements to.
         */
        protected final JavaType _type;
    
        /**
         * Context for deserialization, needed to pass through to deserializer
         */
        protected final DeserializationContext _context;
    
        /**
         * Deserializer for individual element values.
         */
        protected final JsonDeserializer<T> _deserializer;
    
        /**
         * Underlying parser used for reading content to bind. Initialized
         * as not <code>null</code> but set as <code>null</code> when
         * iterator is closed, to denote closing.
         */
        protected final JsonParser _parser;
    
        /**
         * Context to resynchronize to, in case an exception is encountered
         * but caller wants to try to read more elements.
         */
        protected final JsonStreamContext _seqContext;
        
        /**
         * If not null, "value to update" instead of creating a new instance
         * for each call.
         */
        protected final T _updatedValue;
        
        /**
         * Flag that indicates whether input {@link JsonParser} should be closed
         * when we are done or not; generally only called when caller did not
         * pass JsonParser.
         */
        protected final boolean _closeParser;
    
        /*
        /**********************************************************
        /* Parsing state
        /**********************************************************
         */
        
        /**
         * State of the iterator
         */
        protected int _state;
    
        /*
        /**********************************************************
        /* Construction
        /**********************************************************
         */
        
        /**
         * @param managedParser Whether we "own" the {@link JsonParser} passed or not:
         *   if true, it was created by {@link ObjectReader} and code here needs to
         *   close it; if false, it was passed by calling code and should not be
         *   closed by iterator.
         */
        @SuppressWarnings("unchecked")
        protected MappingIterator(JavaType type, JsonParser p, DeserializationContext ctxt,
                JsonDeserializer<?> deser,
                boolean managedParser, Object valueToUpdate)
        {
            _type = type;
            _parser = p;
            _context = ctxt;
            _deserializer = (JsonDeserializer<T>) deser;
            _closeParser = managedParser;
            if (valueToUpdate == null) {
                _updatedValue = null;
            } else {
                _updatedValue = (T) valueToUpdate;
            }
    
            /* Ok: one more thing; we may have to skip START_ARRAY, assuming
             * "wrapped" sequence; but this is ONLY done for 'managed' parsers
             * and never if JsonParser was directly passed by caller (if it
             * was, caller must have either positioned it over first token of
             * the first element, or cleared the START_ARRAY token explicitly).
             * Note, however, that we do not try to guess whether this could be
             * an unwrapped sequence of arrays/Lists: we just assume it is wrapped;
             * and if not, caller needs to hand us JsonParser instead, pointing to
             * the first token of the first element.
             */
            if (p == null) { // can this occur?
                _seqContext = null;
                _state = STATE_CLOSED;
            } else {
                JsonStreamContext sctxt = p.getParsingContext();
                if (managedParser && p.isExpectedStartArrayToken()) {
                    // If pointing to START_ARRAY, context should be that ARRAY
                    p.clearCurrentToken();
                } else {
                    // regardless, recovery context should be whatever context we have now,
                    // with sole exception of pointing to a start marker, in which case it's
                    // the parent
                    JsonToken t = p.currentToken();
                    if ((t == JsonToken.START_OBJECT) || (t == JsonToken.START_ARRAY)) {
                        sctxt = sctxt.getParent();
                    }
                }
                _seqContext = sctxt;
                _state = STATE_MAY_HAVE_VALUE;
            }
        }
    
        /**
         * Method for getting an "empty" iterator instance: one that never
         * has more values; may be freely shared.
         *
         * @since 2.10 Existed earlier but {@code public} since 2.10
         */
        @SuppressWarnings("unchecked")
        public static <T> MappingIterator<T> emptyIterator() {
            return (MappingIterator<T>) EMPTY_ITERATOR;
        }
    
        /*
        /**********************************************************
        /* Basic iterator impl
        /**********************************************************
         */
    
        @Override
        public boolean hasNext()
        {
            try {
                return hasNextValue();
            } catch (JsonMappingException e) {
                return (Boolean) _handleMappingException(e);
            } catch (IOException e) {
                return (Boolean) _handleIOException(e);
            }
        }
        
        @SuppressWarnings("unchecked")
        @Override
        public T next()
        {
            try {
                return nextValue();
            } catch (JsonMappingException e) {
                return (T) _handleMappingException(e);
            } catch (IOException e) {
                return (T) _handleIOException(e);
            }
        }
    
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
        @Override
        public void close() throws IOException {
            if (_state != STATE_CLOSED) {
                _state = STATE_CLOSED;
                if (_parser != null) {
                    _parser.close();
                }
            }
        }
    
        /*
        /**********************************************************
        /* Extended API, iteration
        /**********************************************************
         */
    
        /**
         * Equivalent of {@link #next} but one that may throw checked
         * exceptions from Jackson due to invalid input.
         */
        public boolean hasNextValue() throws IOException
        {
            switch (_state) {
            case STATE_CLOSED:
                return false;
            case STATE_NEED_RESYNC:
                _resync();
                // fall-through
            case STATE_MAY_HAVE_VALUE:
                JsonToken t = _parser.currentToken();
                if (t == null) { // un-initialized or cleared; find next
                    t = _parser.nextToken();
                    // If EOF, no more, or if we hit END_ARRAY (although we don't clear the token).
                    if (t == null || t == JsonToken.END_ARRAY) {
                        _state = STATE_CLOSED;
                        if (_closeParser && (_parser != null)) {
                            _parser.close();
                        }
                        return false;
                    }
                }
                _state = STATE_HAS_VALUE;
                return true;
            case STATE_HAS_VALUE:
                // fall through
            }
            return true;
        }
    
        public T nextValue() throws IOException
        {
            switch (_state) {
            case STATE_CLOSED:
                return _throwNoSuchElement();
            case STATE_NEED_RESYNC: // fall-through, will do re-sync
            case STATE_MAY_HAVE_VALUE:
                if (!hasNextValue()) {
                    return _throwNoSuchElement();
                }
                break;
            case STATE_HAS_VALUE:
                break;
            }
    
            int nextState = STATE_NEED_RESYNC;
            try {
                T value;
                if (_updatedValue == null) {
                    value = _deserializer.deserialize(_parser, _context);
                } else{
                    _deserializer.deserialize(_parser, _context, _updatedValue);
                    value = _updatedValue;
                }
                nextState = STATE_MAY_HAVE_VALUE;
                return value;
            } finally {
                _state = nextState;
                /* 24-Mar-2015, tatu: As per [#733], need to mark token consumed no
                 *   matter what, to avoid infinite loop for certain failure cases.
                 *   For 2.6 need to improve further.
                 */
                _parser.clearCurrentToken();
            }
        }
    
        /**
         * Convenience method for reading all entries accessible via
         * this iterator; resulting container will be a {@link java.util.ArrayList}.
         * 
         * @return List of entries read
         * 
         * @since 2.2
         */
        public List<T> readAll() throws IOException {
            return readAll(new ArrayList<T>());
        }
    
        /**
         * Convenience method for reading all entries accessible via
         * this iterator
         * 
         * @return List of entries read (same as passed-in argument)
         * 
         * @since 2.2
         */
        public <L extends List<? super T>> L readAll(L resultList) throws IOException
        {
            while (hasNextValue()) {
                resultList.add(nextValue());
            }
            return resultList;
        }
    
        /**
         * Convenience method for reading all entries accessible via
         * this iterator
         * 
         * @since 2.5
         */
        public <C extends Collection<? super T>> C readAll(C results) throws IOException
        {
            while (hasNextValue()) {
                results.add(nextValue());
            }
            return results;
        }
        
        /*
        /**********************************************************
        /* Extended API, accessors
        /**********************************************************
         */
    
        /**
         * Accessor for getting underlying parser this iterator uses.
         * 
         * @since 2.2
         */
        public JsonParser getParser() {
            return _parser;
        }
    
        /**
         * Accessor for accessing {@link FormatSchema} that the underlying parser
         * (as per {@link #getParser}) is using, if any; only parser of schema-aware
         * formats use schemas.
         * 
         * @since 2.2
         */
        public FormatSchema getParserSchema() {
        	return _parser.getSchema();
        }
    
        /**
         * Convenience method, functionally equivalent to:
         *<code>
         *   iterator.getParser().getCurrentLocation()
         *</code>
         * 
         * @return Location of the input stream of the underlying parser
         * 
         * @since 2.2.1
         */
        public JsonLocation getCurrentLocation() {
            return _parser.getCurrentLocation();
        }
    
        /*
        /**********************************************************
        /* Helper methods
        /**********************************************************
         */
    
        protected void _resync() throws IOException
        {
            final JsonParser p = _parser;
            // First, a quick check to see if we might have been lucky and no re-sync needed
            if (p.getParsingContext() == _seqContext) {
                return;
            }
    
            while (true) {
                JsonToken t = p.nextToken();
                if ((t == JsonToken.END_ARRAY) || (t == JsonToken.END_OBJECT)) {
                    if (p.getParsingContext() == _seqContext) {
                        p.clearCurrentToken();
                        return;
                    }
                } else if ((t == JsonToken.START_ARRAY) || (t == JsonToken.START_OBJECT)) {
                    p.skipChildren();
                } else if (t == null) {
                    return;
                }
            }
        }
    
        protected <R> R _throwNoSuchElement() {
            throw new NoSuchElementException();
        }
        
        protected <R> R _handleMappingException(JsonMappingException e) {
            throw new RuntimeJsonMappingException(e.getMessage(), e);
        }
    
        protected <R> R _handleIOException(IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    

    com/fasterxml/jackson/databind/MappingIterator.java

     

    ⇒ Jackson Annotations Source Code

    ⇐ Download and Install Jackson Binary Package

    ⇑ Downloading and Reviewing jackson-*.jar

    ⇑⇑ Jackson - Java JSON library

    2022-03-29, 32269👍, 0💬