Package com.fasterxml.jackson.jr.ob

Source Code of com.fasterxml.jackson.jr.ob.JSON

package com.fasterxml.jackson.jr.ob;

import java.io.*;
import java.net.URL;
import java.util.*;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.SegmentedStringWriter;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import com.fasterxml.jackson.core.util.Instantiatable;
import com.fasterxml.jackson.jr.ob.comp.CollectionComposer;
import com.fasterxml.jackson.jr.ob.comp.ComposerBase;
import com.fasterxml.jackson.jr.ob.comp.MapComposer;
import com.fasterxml.jackson.jr.ob.impl.*;

/**
* Main entry point for functionality.
*<p>
* Note that instances are fully immutable, and thereby thread-safe.
*/
public class JSON implements Versioned
{
    /**
     * Simple on/off (enabled/disabled) features for {@link JSON}; used for simple configuration
     * aspects.
     */
    public enum Feature
    {
       /*
       /**********************************************************************
       /* Read-related features
       /**********************************************************************
        */

       /**
        * When reading JSON Numbers, should {@link java.math.BigDecimal} be used
        * for floating-point numbers; or should {@link java.lang.Double} be used.
        * Trade-off is between accuracy -- only {@link java.math.BigDecimal} is
        * guaranteed to store the EXACT decimal value parsed -- and performance
        * ({@link java.lang.Double} is typically faster to parser).
        *<p>
        * Default setting is <code>false</code>, meaning that {@link java.lang.Double}
        * is used.
        */
       USE_BIG_DECIMAL_FOR_FLOATS(false),

       /**
        * When reading JSON Arrays, should matching Java value be of type
        * <code>Object[]</code> (true) or {@link java.util.List} (false)?
        *<p>
        * Default setting is <code>false</code>, meaning that JSON Arrays
        * are bound to {@link java.util.List}s.
        */
       READ_JSON_ARRAYS_AS_JAVA_ARRAYS(false),

       /**
        * This feature can be enabled to reduce memory usage for use cases where
        * resulting container objects ({@link java.util.Map}s and {@link java.util.Collection}s)
        * do not need to mutable (that is, their contents can not changed).
        * If set, reader is allowed to construct immutable (read-only)
        * container objects; and specifically empty {@link java.util.Map}s and
        * {@link java.util.Collection}s can be used to reduce number of
        * objects allocated. In addition, sizes of non-empty containers can
        * be trimmed to exact size.
        *<p>
        * Default setting is <code>false</code>, meaning that reader will have to
        * construct mutable container instance when reading.
        */
       READ_ONLY(false),

       /**
        * This feature can be used to indicate that the reader should preserve
        * order of the properties same as what input document has.
        * Note that it is up to {@link com.fasterxml.jackson.jr.ob.impl.MapBuilder}
        * to support this feature; custom implementations may ignore the setting.
        *<p>
        * Default setting is <code>true</code>, meaning that reader is expected to try to
        * preserve ordering of fields read.
        */
       PRESERVE_FIELD_ORDERING(true),
      
       /**
        * When encountering duplicate keys for JSON Objects, should an exception
        * be thrown or not? If exception is not thrown, <b>the last</b> instance
        * from input document will be used.
        *<p>
        * Default setting is <code>true</code>, meaning that a
        * {@link JSONObjectException} will be thrown if duplicates are encountered.
        */
       FAIL_ON_DUPLICATE_MAP_KEYS(true),

       /**
        * When encountering a JSON Object property name for which there is no
        * matching Bean property, should an exception be thrown (true),
        * or should JSON Property value be quietly skipped (false)?
        *<p>
        * Default setting is <code>false</code>, meaning that unmappable
        * JSON Object properties will simply be ignored.
        */
       FAIL_ON_UNKNOWN_BEAN_PROPERTY(false),

       /*
       /**********************************************************************
       /* Write-related features
       /**********************************************************************
        */

       /**
        * Feature that defines what to do with {@link java.util.Map} entries and Java Bean
        * properties that have null as value: if enabled, they will be written out normally;
        * if disabled, such entries and properties will be ignored.
        *<p>
        * Default setting is <code>false</code> so that any null-valued properties
        * are ignored during serialization.
        */
       WRITE_NULL_PROPERTIES(false),

       /**
        * Feature that determines whether "read-only" properties of Beans
        * (properties that only have a getter but no matching setter) are
        * to be included in Bean serialization or not; if disabled,
        * only properties have have both setter and getter are serialized.
        * Note that feature is only used if {@link #HANDLE_JAVA_BEANS}
        * is also enabled.
        *<p>
        * Feature is enabled by default,
        * so that all Bean properties are serialized.
        */
       WRITE_READONLY_BEAN_PROPERTIES(true),

       /**
        * Feature that determines where Enum values are written using
        * numeric index (true), or String representation from calling
        * {@link Enum#toString()} (false).
        *<p>
        * Feature is disabled by default,
        * so that Enums are serialized as JSON Strings.
        */
       WRITE_ENUMS_USING_INDEX(false),
      
       /**
        * Feature that can be enabled to use "pretty-printing", basic indentation
        * to make resulting JSON easier to read by humans by adding white space
        * such as line feeds and indentation.
        *<p>
        * Default setting is <code>false</code> so that no pretty-printing is done
        * (unless explicitly constructed with a pretty printer object)
        */
       PRETTY_PRINT_OUTPUT(false),
      
       /**
        * Feature that determines whether <code>JsonGenerator.flush()</code> is
        * called after <code>writeJSON()</code> method <b>that takes JsonGenerator
        * as an argument</b> completes (that is, does NOT affect methods
        * that use other destinations).
        * This usually makes sense; but there are cases where flushing
        * should not be forced: for example when underlying stream is
        * compressing and flush() causes compression state to be flushed
        * (which occurs with some compression codecs).
        *<p>
        * Feature is enabled by default.
        */
       FLUSH_AFTER_WRITE_VALUE(true),

       /**
        * Feature that determines what happens when we encounter a value of
        * unrecognized type for which we do not have handling: if enabled,
        * will throw a {@JsonObjectException}, if disabled simply
        * calls {@link Object#toString} and uses that JSON String as serialization.
        *<p>
        * NOTE: if {@link #HANDLE_JAVA_BEANS} is enabled, this setting typically
        * has no effect, since otherwise unknown types are recognized as
        * Bean types.
        *
        *<p>
        * Feature is disabled by default
        * so that no exceptions are thrown.
        */
       FAIL_ON_UNKNOWN_TYPE_WRITE(false),

       /*
       /**********************************************************************
       /* Other features
       /**********************************************************************
        */

       /**
        * Feature that determines whether Bean types (Java objects with
        * getters and setters that expose state to serialize) will be
        * recognized and handled or not.
        * When enabled, any types that are not recognized as standard JDK
        * data structures, primitives or wrapper values will be introspected
        * and handled as Java Beans (can be read/written as long as JSON
        * matches properties discovered); when disabled, they may only be serialized
        * (using {@link Object#toString} method), and can not be deserialized.
        *<p>
        * Feature is enabled by default, but can be disabled do avoid use
        * of Bean reflection for cases where it is not desired.
        */
       HANDLE_JAVA_BEANS(true),
      
       /**
        * Feature that determines whether access to {@link java.lang.reflect.Method}s and
        * {@link java.lang.reflect.Constructor}s that are used with dynamically
        * introspected Beans may be forced using
        * {@link java.lang.reflect.AccessibleObject#setAccessible} or not.
        *<p>
        * Feature is enabled by default, so that access may be forced.
        */
       FORCE_REFLECTION_ACCESS(true),
      
       ;

       /*
       /**********************************************************************
       /* Enum impl
       /**********************************************************************
        */

       private final boolean _defaultState;

       private final int _mask;
      
       private Feature(boolean defaultState) {
           _defaultState = defaultState;
           _mask = (1 << ordinal());
       }

       public static int defaults()
       {
           int flags = 0;
           for (Feature value : values()) {
               if (value.enabledByDefault()) {
                   flags |= value.mask();
               }
           }
           return flags;
       }
      
       public final boolean enabledByDefault() { return _defaultState; }

       public final int mask() { return _mask; }

       public final boolean isDisabled(int flags) {
           return (flags & _mask) == 0;
       }
       public final boolean isEnabled(int flags) {
           return (flags & _mask) != 0;
       }
   }
   
    // Important: has to come before 'std' instance, since it refers to it
    private final static int DEFAULT_FEATURES = Feature.defaults();

    /**
     * Singleton instance with standard, default configuration.
     * May be used with direct references like:
     *<pre>
     *   String json = JSON.std.asString(map);
     *</pre>
     */
    public final static JSON std = new JSON();

    /*
    /**********************************************************************
    /* Configuration, helper objects
    /**********************************************************************
     */

    /**
     * Underlying JSON factory used for creating Streaming parsers and
     * generators.
     */
    protected final JsonFactory _jsonFactory;

    /**
     * Optional handler for {@link TreeNode} values: if defined, we can
     * read and write {@link TreeNode} instances that codec supports.
     */
    protected final TreeCodec _treeCodec;
   
    /**
     * Blueprint instance of the reader to use for reading JSON as simple
     * Objects.
     */
    protected final JSONReader _reader;

    /**
     * Blueprint isntance of the writer to use for writing JSON given
     * simple Objects.
     */
    protected final JSONWriter _writer;
   
    /*
    /**********************************************************************
    /* Configuration, simple settings
    /**********************************************************************
     */

    protected final int _features;

    protected final PrettyPrinter _prettyPrinter;
   
    /*
    /**********************************************************************
    /* Basic construction
    /**********************************************************************
     */

    public JSON() {
        this(DEFAULT_FEATURES, new JsonFactory(), null);
    }

    protected JSON(int features,
            JsonFactory jsonF, TreeCodec trees)
    {
        this(features, jsonF, trees,
                null, null, // reader, writer
                null);
    }
   
    protected JSON(int features,
            JsonFactory jsonF, TreeCodec trees,
            JSONReader r, JSONWriter w,
            PrettyPrinter pp)
    {
        _features = features;
        _jsonFactory = jsonF;
        _treeCodec = trees;
        _reader = (r == null) ? _defaultReader(features, trees) : r;
        _writer = (w == null) ? _defaultWriter(features, trees) : w;
        _prettyPrinter = pp;
    }

    protected JSONReader _defaultReader(int features, TreeCodec tc) {
        return new JSONReader(features, TypeDetector.forReader(features), tc,
                CollectionBuilder.defaultImpl(), MapBuilder.defaultImpl());
    }

    protected JSONWriter _defaultWriter(int features, TreeCodec tc) {
        return new JSONWriter(features, TypeDetector.forWriter(features), tc);
    }
   
    /*
    /**********************************************************************
    /* Adapting
    /**********************************************************************
     */

    /**
     * Convenience method for constructing an adapter that uses this
     * instance as a {@link ObjectCodec}
     */
    public ObjectCodec asCodec() {
        return new JSONAsObjectCodec(this);
    }
   
    /*
    /**********************************************************************
    /* Versioned
    /**********************************************************************
     */
   
    @Override
    public Version version() {
        return PackageVersion.VERSION;
    }
   
    /*
    /**********************************************************************
    /* Mutant factories
    /**********************************************************************
     */

    public JSON with(JsonFactory f)
    {
        if (f == _jsonFactory) {
            return this;
        }
        return _with(_features, f, _treeCodec, _reader, _writer, _prettyPrinter);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link TreeCodec},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(TreeCodec c)
    {
        if (c == _treeCodec) {
            return this;
        }
        return _with(_features, _jsonFactory, c,
                _reader, _writer.with(c), _prettyPrinter);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link JSONReader},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(JSONReader r)
    {
        if (r == _reader) {
            return this;
        }
        return _with(_features, _jsonFactory, _treeCodec,
                r, _writer, _prettyPrinter);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link JSONWriter},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(JSONWriter w)
    {
        if (w == _writer) {
            return this;
        }
        return _with( _features, _jsonFactory, _treeCodec,
                _reader, w, _prettyPrinter);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link PrettyPrinter},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(PrettyPrinter pp)
    {
        if (_prettyPrinter == pp) {
            return this;
        }
        return _with(_features, _jsonFactory, _treeCodec,
                _reader, _writer, pp);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link MapBuilder},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(MapBuilder b) {
        JSONReader r = _reader.with(b);
        if (r == _reader) {
            return this;
        }
        return _with(_features, _jsonFactory, _treeCodec,
                r, _writer, _prettyPrinter);
    }

    /**
     * Mutant factory for constructing an instance with specified {@link CollectionBuilder},
     * and returning new instance (or, if there would be no change, this instance).
     */
    public JSON with(CollectionBuilder b) {
        JSONReader r = _reader.with(b);
        if (r == _reader) {
            return this;
        }
        return _with(_features, _jsonFactory, _treeCodec,
                r, _writer, _prettyPrinter);
    }
   
    /**
     * Mutant factory for constructing an instance with specified feature
     * enabled or disabled (depending on <code>state</codec>), and returning
     * an instance with that setting; this may either be this instance (if feature
     * already had specified state), or a newly constructed instance.
     */
    public JSON with(Feature feature, boolean state)
    {
        int f = _features;
        if (state) {
            f |= feature.mask();
        } else {
            f &= ~feature.mask();
        }
        return _with(f);
    }
   
    /**
     * Mutant factory for constructing an instance with specified features
     * enabled.
     */
    public JSON with(Feature ... features)
    {
        int flags = _features;
        for (Feature feature : features) {
            flags |= feature.mask();
        }
        return _with(flags);
    }

    /**
     * Mutant factory for constructing an instance with specified features
     * disabled.
     */
    public JSON without(Feature ... features)
    {
        int flags = _features;
        for (Feature feature : features) {
            flags &= ~feature.mask();
        }
        return _with(flags);
    }

    /**
     * Internal mutant factory method used for constructing
     */
    protected final JSON _with(int features)
    {
        if (_features == features) {
            return this;
        }
        return _with(features, _jsonFactory, _treeCodec,
                _reader.withFeatures(features), _writer.withFeatures(features),
                _prettyPrinter);
    }
   
    /*
    /**********************************************************************
    /* Methods sub-classes must override
    /**********************************************************************
     */
   
    protected final JSON _with(int features,
            JsonFactory jsonF, TreeCodec trees,
            JSONReader reader, JSONWriter writer,
            PrettyPrinter pp)
    {
        if (getClass() != JSON.class) {
            throw new IllegalStateException("Sub-classes MUST override _with(...)");
        }
        return new JSON(features, jsonF, trees, reader, writer, pp);
    }
   
    /*
    /**********************************************************************
    /* Simple accessors
    /**********************************************************************
     */

    public TreeCodec getTreeCodec() {
        return _treeCodec;
    }

    public JsonFactory getStreamingFactory() {
        return _jsonFactory;
    }

    public final boolean isEnabled(Feature f) {
        return (f.mask() & _features) != 0;
    }
   
    /*
    /**********************************************************************
    /* API: writing Simple objects as JSON
    /**********************************************************************
     */

    @SuppressWarnings("resource")
    public String asString(Object value) throws IOException, JSONObjectException
    {
        SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
        try {
            _writeAndClose(value, _jsonFactory.createGenerator(sw));
        } catch (JsonProcessingException e) { // to support [JACKSON-758]
            throw e;
        } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
            throw JSONObjectException.fromUnexpectedIOE(e);
        }
        return sw.getAndClear();
    }

    @SuppressWarnings("resource")
    public byte[] asBytes(Object value) throws IOException, JSONObjectException
    {
        ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler());
        try {
            _writeAndClose(value, _jsonFactory.createGenerator(bb, JsonEncoding.UTF8));
        } catch (JsonProcessingException e) { // to support [JACKSON-758]
            throw e;
        } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
            throw JSONObjectException.fromUnexpectedIOE(e);
        }
        byte[] result = bb.toByteArray();
        bb.release();
        return result;
    }

    public void write(Object value, JsonGenerator jgen) throws IOException, JSONObjectException {
        // NOTE: no call to _config(); assumed to be fully configured
        _writerForOperation(jgen).writeValue(value);
        if (Feature.FLUSH_AFTER_WRITE_VALUE.isEnabled(_features)) {
            jgen.flush();
        }
    }

    public void write(Object value, OutputStream out) throws IOException, JSONObjectException {
        _writeAndClose(value, _jsonFactory.createGenerator(out));
    }

    public void write(Object value, Writer w) throws IOException, JSONObjectException {
        _writeAndClose(value, _jsonFactory.createGenerator(w));
    }

    public void write(Object value, File f) throws IOException, JSONObjectException {
        _writeAndClose(value, _jsonFactory.createGenerator(f, JsonEncoding.UTF8));
    }
   
    /*
    /**********************************************************************
    /* API: writing using Composers
    /**********************************************************************
     */

    public JSONComposer<OutputStream> composeUsing(JsonGenerator gen) throws IOException, JSONObjectException {
        return JSONComposer.streamComposer(_features, gen, false);
    }
   
    public JSONComposer<OutputStream> composeTo(OutputStream out) throws IOException, JSONObjectException {
        return JSONComposer.streamComposer(_features,
                _jsonFactory.createGenerator(out), true);
    }

    public JSONComposer<OutputStream> composeTo(Writer w) throws IOException, JSONObjectException {
        return JSONComposer.streamComposer(_features,
                _jsonFactory.createGenerator(w), true);
    }

    public JSONComposer<OutputStream> composeTo(File f) throws IOException, JSONObjectException {
        return JSONComposer.streamComposer(_features,
                _jsonFactory.createGenerator(f, JsonEncoding.UTF8), true);
    }
   
    @SuppressWarnings("resource")
    public JSONComposer<String> composeString() throws IOException, JSONObjectException {
        SegmentedStringWriter out = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
        return JSONComposer.stringComposer(_features, _jsonFactory.createGenerator(out), out);
    }

    @SuppressWarnings("resource")
    public JSONComposer<byte[]> composeBytes() throws IOException, JSONObjectException {
        ByteArrayBuilder out = new ByteArrayBuilder(_jsonFactory._getBufferRecycler());
        return JSONComposer.bytesComposer(_features, _jsonFactory.createGenerator(out), out);
    }

    public CollectionComposer<?,List<Object>> composeList() {
        List<Object> list = new ArrayList<Object>();
        return composeCollection(list);
    }

    public <C extends Collection<Object>> CollectionComposer<?,C> composeCollection(C collection) {
        return new CollectionComposer<ComposerBase,C>(collection);
    }
   
    public MapComposer<?> composeMap() {
        return composeMap(new LinkedHashMap<String,Object>());
    }

    public MapComposer<?> composeMap(Map<String,Object> map) {
        return new MapComposer<ComposerBase>(map);
    }
   
    /*
    /**********************************************************************
    /* API: reading JSON as Simple Objects
    /**********************************************************************
     */

    @SuppressWarnings("resource")
    public List<Object> listFrom(Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            // note: no call to _config(), should come pre-configured
            JsonParser jp = _initForReading((JsonParser) source);
            List<Object> result = _readerForOperation(jp).readList();
            // Need to consume the token too
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            List<Object> result = _readerForOperation(jp).readList();
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }

    @SuppressWarnings("resource")
    public <T> List<T> listOfFrom(Class<T> type, Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            // note: no call to _config(), should come pre-configured
            JsonParser jp = _initForReading((JsonParser) source);
            List<T> result = _readerForOperation(jp).readListOf(type);
            // Need to consume the token too
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            List<T> result = _readerForOperation(jp).readListOf(type);
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }
   
    @SuppressWarnings("resource")
    public Object[] arrayFrom(Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            JsonParser jp = _initForReading((JsonParser) source);
            Object[] result = _readerForOperation(jp).readArray();
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            Object[] result = _readerForOperation(jp).readArray();
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }

    @SuppressWarnings("resource")
    public <T> T[] arrayOfFrom(Class<T> type, Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            JsonParser jp = _initForReading((JsonParser) source);
            T[] result = _readerForOperation(jp).readArrayOf(type);
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            T[] result = _readerForOperation(jp).readArrayOf(type);
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }
   
    @SuppressWarnings({ "unchecked", "resource" })
    public <T> Map<T,Object> mapFrom(Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            JsonParser jp = _initForReading((JsonParser) source);
            Map<Object,Object> result = _readerForOperation(jp).readMap();
            jp.clearCurrentToken();
            return (Map<T,Object>) result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            Map<Object,Object> result = _readerForOperation(jp).readMap();
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return (Map<T,Object>) result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }

    @SuppressWarnings("resource")
    public <T> T beanFrom(Class<T> type, Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            JsonParser jp = _initForReading((JsonParser) source);
            T result = _readerForOperation(jp).readBean(type);
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            T result = _readerForOperation(jp).readBean(type);
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }
   
    /**
     * Read method that will take given JSON Source (of one of supported types),
     * read contents and map it to one of simple mappings ({@link java.util.Map}
     * for JSON Objects, {@link java.util.List} for JSON Arrays, {@link java.lang.String}
     * for JSON Strings, null for JSON null, {@link java.lang.Boolean} for JSON booleans
     * and {@link java.lang.Number} for JSON numbers.
     *<p>
     * Supported source types include:
     *<ul>
     * <li>{@link java.io.InputStream}</li>
     * <li>{@link java.io.Reader}</li>
     * <li>{@link java.io.File}</li>
     * <li>{@link java.net.URL}</li>
     * <li>{@link java.lang.String}</li>
     * <li><code>byte[]</code></li>
     * <li><code>char[]</code></li>
     *</ul>
     */
    @SuppressWarnings("resource")
    public Object anyFrom(Object source) throws IOException, JSONObjectException
    {
        if (source instanceof JsonParser) {
            JsonParser jp = _initForReading((JsonParser) source);
            Object result = _readerForOperation(jp).readValue();
            jp.clearCurrentToken();
            return result;
        }
        JsonParser jp = _parser(source);
        try {
            _initForReading(_config(jp));
            Object result = _readerForOperation(jp).readValue();
            JsonParser jp0 = jp;
            jp = null;
            _close(jp0, null);
            return result;
        } catch (Exception e) {
            _close(jp, e);
            return null;
        }
    }
   
    /*
    /**********************************************************************
    /* Internal methods, writing
    /**********************************************************************
     */

    protected final void _writeAndClose(Object value, JsonGenerator jgen)
        throws IOException, JSONObjectException
    {
        boolean closed = false;
        try {
            _config(jgen);
            _writerForOperation(jgen).writeValue(value);
            closed = true;
            jgen.close();
        } finally {
            if (!closed) {
                // need to catch possible failure, so as not to mask problem
                try {
                    jgen.close();
                } catch (IOException ioe) { }
            }
        }
    }

    protected JSONWriter _writerForOperation(JsonGenerator jgen) {
        return _writer.perOperationInstance(jgen);
    }

    /*
    /**********************************************************************
    /* Internal methods, reading
    /**********************************************************************
     */
   
    protected JSONReader _readerForOperation(JsonParser jp) {
        return _reader.perOperationInstance(jp);
    }

    protected JsonParser _parser(Object source) throws IOException, JSONObjectException
    {
        final JsonFactory f = _jsonFactory;
        final Class<?> type = source.getClass();
        if (type == String.class) {
            return f.createParser((String) source);
        }
        if (source instanceof InputStream) {
            return f.createParser((InputStream) source);
        }
        if (source instanceof Reader) {
            return f.createParser((Reader) source);
        }
        if (type == byte[].class) {
            return f.createParser((byte[]) source);
        }
        if (source instanceof URL) {
            return f.createParser((URL) source);
        }
        if (type == char[].class) {
            return f.createParser(new CharArrayReader((char[]) source));
        }
        if (source instanceof CharSequence) {
            return f.createParser(((CharSequence) source).toString());
        }
        if (source instanceof JsonParser) { // should never be called with this
            throw new IllegalStateException();
        }
        throw new JSONObjectException("Can not use Source of type "+source.getClass().getName()
                +" as input (use an InputStream, Reader, String, byte[], File or URL");
    }

    protected JsonParser _initForReading(JsonParser jp)
        throws IOException, JsonProcessingException
    {
        /* First: must point to a token; if not pointing to one, advance.
         * This occurs before first read from JsonParser, as well as
         * after clearing of current token.
         */
        JsonToken t = jp.getCurrentToken();
        if (t == null) { // and then we must get something...
            t = jp.nextToken();
            if (t == null) { // not cool is it?
                throw JSONObjectException.from(jp, "No content to map due to end-of-input");
            }
        }
        return jp;
    }
   
    /*
    /**********************************************************************
    /* Internal methods, other
    /**********************************************************************
     */

    protected JsonGenerator _config(JsonGenerator jgen)
    {
        // First, possible pretty printing
        PrettyPrinter pp = _prettyPrinter;
        if (pp != null) {
            if (pp instanceof Instantiatable<?>) {
                pp = (PrettyPrinter) ((Instantiatable<?>) pp).createInstance();
            }
            jgen.setPrettyPrinter(pp);
        } else if (isEnabled(Feature.PRETTY_PRINT_OUTPUT)) {
            jgen.useDefaultPrettyPrinter();
        }
        return jgen;
    }

    protected JsonParser _config(JsonParser jp)
    {
        // nothing to do, yet
        return jp;
    }

    protected void _close(Closeable cl) {
        try {
            cl.close();
        } catch (IOException ioe) { }
    }

    protected void _close(Closeable cl, Exception e) throws IOException {
        if (cl != null) {
            if (e == null) {
                cl.close();
            } else {
                try {
                    cl.close();
                } catch (Exception secondaryEx) {
                    // what should we do here, if anything?
                }
            }
        }
        if (e != null) {
            if (e instanceof IOException) {
                throw (IOException) e;
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new IOException(e); // should never occur
        }
    }
}
TOP

Related Classes of com.fasterxml.jackson.jr.ob.JSON

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.