Java tutorial
package com.fasterxml.jackson.databind; import java.io.*; import java.text.DateFormat; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.Instantiatable; import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; import com.fasterxml.jackson.databind.cfg.ContextAttributes; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.SerializerFactory; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Builder object that can be used for per-serialization configuration of * serialization parameters, such as JSON View and root type to use. * (and thus fully thread-safe with no external synchronization); * new instances are constructed for different configurations. * Instances are initially constructed by {@link ObjectMapper} and can be * reused in completely thread-safe manner with no explicit synchronization */ public class ObjectWriter implements Versioned, java.io.Serializable // since 2.1 { private static final long serialVersionUID = -7040667122552707164L; /** * We need to keep track of explicit disabling of pretty printing; * easiest to do by a token value. */ protected final static PrettyPrinter NULL_PRETTY_PRINTER = new MinimalPrettyPrinter(); /* /********************************************************** /* Immutable configuration from ObjectMapper /********************************************************** */ /** * General serialization configuration settings */ protected final SerializationConfig _config; protected final DefaultSerializerProvider _serializerProvider; protected final SerializerFactory _serializerFactory; /** * Factory used for constructing {@link JsonGenerator}s */ protected final JsonFactory _generatorFactory; /* /********************************************************** /* Configuration that can be changed via mutant factories /********************************************************** */ /** * Specified root serialization type to use; can be same * as runtime type, but usually one of its super types */ protected final JavaType _rootType; /** * We may pre-fetch serializer if {@link #_rootType} * is known, and if so, reuse it afterwards. * This allows avoiding further serializer lookups and increases * performance a bit on cases where readers are reused. * * @since 2.1 */ protected final JsonSerializer<Object> _rootSerializer; /** * To allow for dynamic enabling/disabling of pretty printing, * pretty printer can be optionally configured for writer * as well */ protected final PrettyPrinter _prettyPrinter; /** * When using data format that uses a schema, schema is passed * to generator. */ protected final FormatSchema _schema; /** * Caller may want to specify character escaping details, either as * defaults, or on call-by-call basis. * * @since 2.3 */ protected final CharacterEscapes _characterEscapes; /* /********************************************************** /* Derived settings /********************************************************** */ /** * @since 2.3 */ protected final boolean _cfgBigDecimalAsPlain; /* /********************************************************** /* Life-cycle, constructors /********************************************************** */ /** * Constructor used by {@link ObjectMapper} for initial instantiation */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, JavaType rootType, PrettyPrinter pp) { _config = config; _cfgBigDecimalAsPlain = _config.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN); _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _prettyPrinter = pp; _schema = null; _characterEscapes = null; // 29-Apr-2014, tatu: There is no "untyped serializer", so: if (rootType == null || rootType.hasRawClass(Object.class)) { _rootType = null; _rootSerializer = null; } else { _rootType = rootType.withStaticTyping(); _rootSerializer = _prefetchRootSerializer(config, _rootType); } } /** * Alternative constructor for initial instantiation by {@link ObjectMapper} */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config) { _config = config; _cfgBigDecimalAsPlain = _config.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN); _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _rootType = null; _rootSerializer = null; _prettyPrinter = null; _schema = null; _characterEscapes = null; } /** * Alternative constructor for initial instantiation by {@link ObjectMapper} */ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, FormatSchema s) { _config = config; _cfgBigDecimalAsPlain = _config.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN); _serializerProvider = mapper._serializerProvider; _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _rootType = null; _rootSerializer = null; _prettyPrinter = null; _schema = s; _characterEscapes = null; } /** * Copy constructor used for building variations. */ protected ObjectWriter(ObjectWriter base, SerializationConfig config, JavaType rootType, JsonSerializer<Object> rootSer, PrettyPrinter pp, FormatSchema s, CharacterEscapes escapes) { _config = config; _cfgBigDecimalAsPlain = _config.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN); _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = base._generatorFactory; _rootType = rootType; _rootSerializer = rootSer; _prettyPrinter = pp; _schema = s; _characterEscapes = escapes; } /** * Copy constructor used for building variations. */ protected ObjectWriter(ObjectWriter base, SerializationConfig config) { _config = config; _cfgBigDecimalAsPlain = _config.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN); _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = base._generatorFactory; _schema = base._schema; _characterEscapes = base._characterEscapes; _rootType = base._rootType; _rootSerializer = base._rootSerializer; _prettyPrinter = base._prettyPrinter; } /** * @since 2.3 */ protected ObjectWriter(ObjectWriter base, JsonFactory f) { // may need to override ordering, based on data format capabilities _config = base._config.with(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, f.requiresPropertyOrdering()); _cfgBigDecimalAsPlain = base._cfgBigDecimalAsPlain; _serializerProvider = base._serializerProvider; _serializerFactory = base._serializerFactory; _generatorFactory = base._generatorFactory; _schema = base._schema; _characterEscapes = base._characterEscapes; _rootType = base._rootType; _rootSerializer = base._rootSerializer; _prettyPrinter = base._prettyPrinter; } /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; } /* /********************************************************** /* Life-cycle, fluent factories /********************************************************** */ /** * Method for constructing a new instance that is configured * with specified feature enabled. */ public ObjectWriter with(SerializationFeature feature) { SerializationConfig newConfig = _config.with(feature); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter with(SerializationFeature first, SerializationFeature... other) { SerializationConfig newConfig = _config.with(first, other); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter withFeatures(SerializationFeature... features) { SerializationConfig newConfig = _config.withFeatures(features); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method for constructing a new instance that is configured * with specified feature enabled. */ public ObjectWriter without(SerializationFeature feature) { SerializationConfig newConfig = _config.without(feature); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter without(SerializationFeature first, SerializationFeature... other) { SerializationConfig newConfig = _config.without(first, other); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method for constructing a new instance that is configured * with specified features enabled. */ public ObjectWriter withoutFeatures(SerializationFeature... features) { SerializationConfig newConfig = _config.withoutFeatures(features); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Fluent factory method that will construct a new writer instance that will * use specified date format for serializing dates; or if null passed, one * that will serialize dates as numeric timestamps. *<p> * Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter with(DateFormat df) { SerializationConfig newConfig = _config.with(df); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method that will construct a new instance that will use the default * pretty printer for serialization. */ public ObjectWriter withDefaultPrettyPrinter() { return with(new DefaultPrettyPrinter()); } /** * Method that will construct a new instance that uses specified * provider for resolving filter instances by id. */ public ObjectWriter with(FilterProvider filterProvider) { return (filterProvider == _config.getFilterProvider()) ? this : new ObjectWriter(this, _config.withFilters(filterProvider)); } /** * Method that will construct a new instance that will use specified pretty * printer (or, if null, will not do any pretty-printing) */ public ObjectWriter with(PrettyPrinter pp) { if (pp == _prettyPrinter) { return this; } // since null would mean "don't care", need to use placeholder to indicate "disable" if (pp == null) { pp = NULL_PRETTY_PRINTER; } return new ObjectWriter(this, _config, _rootType, _rootSerializer, pp, _schema, _characterEscapes); } /** * Method for constructing a new instance with configuration that * specifies what root name to use for "root element wrapping". * See {@link SerializationConfig#withRootName(String)} for details. *<p> * Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter withRootName(String rootName) { SerializationConfig newConfig = _config.withRootName(rootName); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method that will construct a new instance that uses specific format schema * for serialization. *<p> * Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter withSchema(FormatSchema schema) { if (_schema == schema) { return this; } _verifySchemaType(schema); return new ObjectWriter(this, _config, _rootType, _rootSerializer, _prettyPrinter, schema, _characterEscapes); } /** * Method that will construct a new instance that uses specific type * as the root type for serialization, instead of runtime dynamic * type of the root object itself. *<p> * Note that method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter withType(JavaType rootType) { JsonSerializer<Object> rootSer; if (rootType == null || rootType.hasRawClass(Object.class)) { rootType = null; rootSer = null; } else { // 15-Mar-2013, tatu: Important! Indicate that static typing is needed: rootType = rootType.withStaticTyping(); rootSer = _prefetchRootSerializer(_config, rootType); } return new ObjectWriter(this, _config, rootType, rootSer, _prettyPrinter, _schema, _characterEscapes); } /** * Method that will construct a new instance that uses specific type * as the root type for serialization, instead of runtime dynamic * type of the root object itself. */ public ObjectWriter withType(Class<?> rootType) { if (rootType == Object.class) { return withType((JavaType) null); } return withType(_config.constructType(rootType)); } public ObjectWriter withType(TypeReference<?> rootType) { return withType(_config.getTypeFactory().constructType(rootType.getType())); } /** * Method that will construct a new instance that uses specified * serialization view for serialization (with null basically disables * view processing) *<p> * Note that the method does NOT change state of this reader, but * rather construct and returns a newly configured instance. */ public ObjectWriter withView(Class<?> view) { SerializationConfig newConfig = _config.withView(view); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } public ObjectWriter with(Locale l) { SerializationConfig newConfig = _config.with(l); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } public ObjectWriter with(TimeZone tz) { SerializationConfig newConfig = _config.with(tz); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * Method that will construct a new instance that uses specified default * {@link Base64Variant} for base64 encoding * * @since 2.1 */ public ObjectWriter with(Base64Variant b64variant) { SerializationConfig newConfig = _config.with(b64variant); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * @since 2.3 */ public ObjectWriter with(CharacterEscapes escapes) { if (_characterEscapes == escapes) { return this; } return new ObjectWriter(this, _config, _rootType, _rootSerializer, _prettyPrinter, _schema, escapes); } /** * @since 2.3 */ public ObjectWriter with(JsonFactory f) { return (f == _generatorFactory) ? this : new ObjectWriter(this, f); } /** * @since 2.3 */ public ObjectWriter with(ContextAttributes attrs) { SerializationConfig newConfig = _config.with(attrs); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * @since 2.3 */ public ObjectWriter withAttributes(Map<Object, Object> attrs) { SerializationConfig newConfig = _config.withAttributes(attrs); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * @since 2.3 */ public ObjectWriter withAttribute(Object key, Object value) { SerializationConfig newConfig = _config.withAttribute(key, value); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /** * @since 2.3 */ public ObjectWriter withoutAttribute(Object key) { SerializationConfig newConfig = _config.withoutAttribute(key); return (newConfig == _config) ? this : new ObjectWriter(this, newConfig); } /* /********************************************************** /* Simple accessors /********************************************************** */ public boolean isEnabled(SerializationFeature f) { return _config.isEnabled(f); } public boolean isEnabled(MapperFeature f) { return _config.isEnabled(f); } public boolean isEnabled(JsonParser.Feature f) { return _generatorFactory.isEnabled(f); } /** * @since 2.2 */ public SerializationConfig getConfig() { return _config; } /** * @deprecated Since 2.2, use {@link #getFactory} instead. */ @Deprecated public JsonFactory getJsonFactory() { return _generatorFactory; } /** * @since 2.2 */ public JsonFactory getFactory() { return _generatorFactory; } public TypeFactory getTypeFactory() { return _config.getTypeFactory(); } /** * Diagnostics method that can be called to check whether this writer * has pre-fetched serializer to use: pre-fetching improves performance * when writer instances are reused as it avoids a per-call serializer * lookup. * * @since 2.2 */ public boolean hasPrefetchedSerializer() { return _rootSerializer != null; } /** * @since 2.3 */ public ContextAttributes getAttributes() { return _config.getAttributes(); } /* /********************************************************** /* Serialization methods; ones from ObjectCodec first /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, using provided {@link JsonGenerator}. */ public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonGenerationException, JsonMappingException { // 10-Aug-2012, tatu: As per [Issue#12], may need to force PrettyPrinter settings, so: _configureJsonGenerator(jgen); if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { _writeCloseableValue(jgen, value, _config); } else { if (_rootType == null) { _serializerProvider(_config).serializeValue(jgen, value); } else { _serializerProvider(_config).serializeValue(jgen, value, _rootType, _rootSerializer); } if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { jgen.flush(); } } } /* /********************************************************** /* Serialization methods, others /********************************************************** */ /** * Method that can be used to serialize any Java value as * JSON output, written to File provided. */ public void writeValue(File resultFile, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(resultFile, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using output stream provided (using encoding * {@link JsonEncoding#UTF8}). *<p> * Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(out, JsonEncoding.UTF8), value); } /** * Method that can be used to serialize any Java value as * JSON output, using Writer provided. *<p> * Note: method does not close the underlying stream explicitly * here; however, {@link JsonFactory} this mapper uses may choose * to close the stream depending on its settings (by default, * it will try to close it when {@link JsonGenerator} we construct * is closed). */ public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(_generatorFactory.createGenerator(w), value); } /** * Method that can be used to serialize any Java value as * a String. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} * and constructing String, but more efficient. *<p> * Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public String writeValueAsString(Object value) throws JsonProcessingException { // alas, we have to pull the recycler directly here... SegmentedStringWriter sw = new SegmentedStringWriter(_generatorFactory._getBufferRecycler()); try { _configAndWriteValue(_generatorFactory.createGenerator(sw), value); } catch (JsonProcessingException e) { // to support [JACKSON-758] throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } return sw.getAndClear(); } /** * Method that can be used to serialize any Java value as * a byte array. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} * and getting bytes, but more efficient. * Encoding used will be UTF-8. *<p> * Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public byte[] writeValueAsBytes(Object value) throws JsonProcessingException { ByteArrayBuilder bb = new ByteArrayBuilder(_generatorFactory._getBufferRecycler()); try { _configAndWriteValue(_generatorFactory.createGenerator(bb, JsonEncoding.UTF8), value); } catch (JsonProcessingException e) { // to support [JACKSON-758] throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } byte[] result = bb.toByteArray(); bb.release(); return result; } /* /********************************************************** /* Other public methods /********************************************************** */ /** * Method for visiting type hierarchy for given type, using specified visitor. * Visitation uses <code>Serializer</code> hierarchy and related properties *<p> * This method can be used for things like * generating <a href="http://json-schema.org/">Json Schema</a> * instance for specified type. * * @param type Type to generate schema for (possibly with generic signature) * * @since 2.2 */ public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException { if (type == null) { throw new IllegalArgumentException("type must be provided"); } _serializerProvider(_config).acceptJsonFormatVisitor(type, visitor); } public boolean canSerialize(Class<?> type) { return _serializerProvider(_config).hasSerializerFor(type, null); } /** * Method for checking whether instances of given type can be serialized, * and optionally why (as per {@link Throwable} returned). * * @since 2.3 */ public boolean canSerialize(Class<?> type, AtomicReference<Throwable> cause) { return _serializerProvider(_config).hasSerializerFor(type, cause); } /* /********************************************************** /* Overridable helper methods /********************************************************** */ /** * Overridable helper method used for constructing * {@link SerializerProvider} to use for serialization. */ protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) { return _serializerProvider.createInstance(config, _serializerFactory); } /* /********************************************************** /* Internal methods /********************************************************** */ /** * @since 2.2 */ protected void _verifySchemaType(FormatSchema schema) { if (schema != null) { if (!_generatorFactory.canUseSchema(schema)) { throw new IllegalArgumentException("Can not use FormatSchema of type " + schema.getClass().getName() + " for format " + _generatorFactory.getFormatName()); } } } /** * Method called to configure the generator as necessary and then * call write functionality */ protected final void _configAndWriteValue(JsonGenerator jgen, Object value) throws IOException { _configureJsonGenerator(jgen); // [JACKSON-282]: consider Closeable if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { _writeCloseable(jgen, value, _config); return; } boolean closed = false; try { if (_rootType == null) { _serializerProvider(_config).serializeValue(jgen, value); } else { _serializerProvider(_config).serializeValue(jgen, value, _rootType, _rootSerializer); } closed = true; jgen.close(); } finally { /* won't try to close twice; also, must catch exception (so it * will not mask exception that is pending) */ if (!closed) { /* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of * structures, which typically causes more damage. */ jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); try { jgen.close(); } catch (IOException ioe) { } } } } /** * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> * method is to be called right after serialization has been called */ private final void _writeCloseable(JsonGenerator jgen, Object value, SerializationConfig cfg) throws IOException, JsonGenerationException, JsonMappingException { Closeable toClose = (Closeable) value; try { if (_rootType == null) { _serializerProvider(cfg).serializeValue(jgen, value); } else { _serializerProvider(cfg).serializeValue(jgen, value, _rootType, _rootSerializer); } JsonGenerator tmpJgen = jgen; jgen = null; tmpJgen.close(); Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } finally { /* Need to close both generator and value, as long as they haven't yet * been closed */ if (jgen != null) { /* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of * structures, which typically causes more damage. */ jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); try { jgen.close(); } catch (IOException ioe) { } } if (toClose != null) { try { toClose.close(); } catch (IOException ioe) { } } } } /** * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> * method is to be called right after serialization has been called */ private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg) throws IOException, JsonGenerationException, JsonMappingException { Closeable toClose = (Closeable) value; try { if (_rootType == null) { _serializerProvider(cfg).serializeValue(jgen, value); } else { _serializerProvider(cfg).serializeValue(jgen, value, _rootType, _rootSerializer); } if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) { jgen.flush(); } Closeable tmpToClose = toClose; toClose = null; tmpToClose.close(); } finally { if (toClose != null) { try { toClose.close(); } catch (IOException ioe) { } } } } /** * Method called to locate (root) serializer ahead of time, if permitted * by configuration. Method also is NOT to throw an exception if * access fails. */ protected JsonSerializer<Object> _prefetchRootSerializer(SerializationConfig config, JavaType valueType) { if (valueType == null || !_config.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)) { return null; } try { return _serializerProvider(config).findTypedValueSerializer(valueType, true, null); } catch (JsonProcessingException e) { // need to swallow? return null; } } /** * Helper method called to set or override settings of passed-in * {@link JsonGenerator} * * @since 2.1 */ private void _configureJsonGenerator(JsonGenerator jgen) { if (_prettyPrinter != null) { PrettyPrinter pp = _prettyPrinter; if (pp == NULL_PRETTY_PRINTER) { jgen.setPrettyPrinter(null); } else { /* [JACKSON-851]: Better take care of stateful PrettyPrinters... * like the DefaultPrettyPrinter. */ if (pp instanceof Instantiatable<?>) { pp = (PrettyPrinter) ((Instantiatable<?>) pp).createInstance(); } jgen.setPrettyPrinter(pp); } } else if (_config.isEnabled(SerializationFeature.INDENT_OUTPUT)) { jgen.useDefaultPrettyPrinter(); } if (_characterEscapes != null) { jgen.setCharacterEscapes(_characterEscapes); } // [JACKSON-520]: add support for pass-through schema: if (_schema != null) { jgen.setSchema(_schema); } if (_cfgBigDecimalAsPlain) { // should only set if explicitly set; this should work for now: jgen.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); } } }