xref: /aosp_15_r20/external/jackson-databind/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java (revision 0ed15c778abdfe0f5f51f6133673e1619d6e56e4)
1 package com.fasterxml.jackson.databind;
2 
3 import java.io.*;
4 import java.text.*;
5 import java.util.Locale;
6 import java.util.Map;
7 import java.util.TimeZone;
8 import java.util.concurrent.atomic.AtomicReference;
9 
10 import com.fasterxml.jackson.core.*;
11 import com.fasterxml.jackson.core.io.CharacterEscapes;
12 import com.fasterxml.jackson.core.io.SegmentedStringWriter;
13 import com.fasterxml.jackson.core.io.SerializedString;
14 import com.fasterxml.jackson.core.type.TypeReference;
15 import com.fasterxml.jackson.core.util.*;
16 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
17 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
18 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
19 import com.fasterxml.jackson.databind.ser.*;
20 import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer;
21 import com.fasterxml.jackson.databind.type.TypeFactory;
22 import com.fasterxml.jackson.databind.util.ClassUtil;
23 
24 /**
25  * Builder object that can be used for per-serialization configuration of
26  * serialization parameters, such as JSON View and root type to use.
27  * (and thus fully thread-safe with no external synchronization);
28  * new instances are constructed for different configurations.
29  * Instances are initially constructed by {@link ObjectMapper} and can be
30  * reused in completely thread-safe manner with no explicit synchronization
31  */
32 public class ObjectWriter
33     implements Versioned,
34         java.io.Serializable // since 2.1
35 {
36     private static final long serialVersionUID = 1; // since 2.5
37 
38     /**
39      * We need to keep track of explicit disabling of pretty printing;
40      * easiest to do by a token value.
41      */
42     protected final static PrettyPrinter NULL_PRETTY_PRINTER = new MinimalPrettyPrinter();
43 
44     /*
45     /**********************************************************
46     /* Immutable configuration from ObjectMapper
47     /**********************************************************
48      */
49 
50     /**
51      * General serialization configuration settings
52      */
53     protected final SerializationConfig _config;
54 
55     protected final DefaultSerializerProvider _serializerProvider;
56 
57     protected final SerializerFactory _serializerFactory;
58 
59     /**
60      * Factory used for constructing {@link JsonGenerator}s
61      */
62     protected final JsonFactory _generatorFactory;
63 
64     /*
65     /**********************************************************
66     /* Configuration that can be changed via mutant factories
67     /**********************************************************
68      */
69 
70     /**
71      * Container for settings that need to be passed to {@link JsonGenerator}
72      * constructed for serializing values.
73      *
74      * @since 2.5
75      */
76     protected final GeneratorSettings _generatorSettings;
77 
78     /**
79      * We may pre-fetch serializer if root type
80      * is known (has been explicitly declared), and if so, reuse it afterwards.
81      * This allows avoiding further serializer lookups and increases
82      * performance a bit on cases where readers are reused.
83      *
84      * @since 2.5
85      */
86     protected final Prefetch _prefetch;
87 
88     /*
89     /**********************************************************
90     /* Life-cycle, constructors
91     /**********************************************************
92      */
93 
94     /**
95      * Constructor used by {@link ObjectMapper} for initial instantiation
96      */
ObjectWriter(ObjectMapper mapper, SerializationConfig config, JavaType rootType, PrettyPrinter pp)97     protected ObjectWriter(ObjectMapper mapper, SerializationConfig config,
98             JavaType rootType, PrettyPrinter pp)
99     {
100         _config = config;
101         _serializerProvider = mapper._serializerProvider;
102         _serializerFactory = mapper._serializerFactory;
103         _generatorFactory = mapper._jsonFactory;
104         _generatorSettings = (pp == null) ? GeneratorSettings.empty
105                 : new GeneratorSettings(pp, null, null, null);
106 
107         if (rootType == null) {
108             _prefetch = Prefetch.empty;
109         } else if (rootType.hasRawClass(Object.class)) {
110             // 15-Sep-2019, tatu: There is no "untyped serializer", but...
111             //     as per [databind#1093] we do need `TypeSerializer`
112             _prefetch = Prefetch.empty.forRootType(this, rootType);
113         } else {
114             _prefetch = Prefetch.empty.forRootType(this, rootType.withStaticTyping());
115         }
116     }
117 
118     /**
119      * Alternative constructor for initial instantiation by {@link ObjectMapper}
120      */
ObjectWriter(ObjectMapper mapper, SerializationConfig config)121     protected ObjectWriter(ObjectMapper mapper, SerializationConfig config)
122     {
123         _config = config;
124         _serializerProvider = mapper._serializerProvider;
125         _serializerFactory = mapper._serializerFactory;
126         _generatorFactory = mapper._jsonFactory;
127 
128         _generatorSettings = GeneratorSettings.empty;
129         _prefetch = Prefetch.empty;
130     }
131 
132     /**
133      * Alternative constructor for initial instantiation by {@link ObjectMapper}
134      */
ObjectWriter(ObjectMapper mapper, SerializationConfig config, FormatSchema s)135     protected ObjectWriter(ObjectMapper mapper, SerializationConfig config,
136             FormatSchema s)
137     {
138         _config = config;
139 
140         _serializerProvider = mapper._serializerProvider;
141         _serializerFactory = mapper._serializerFactory;
142         _generatorFactory = mapper._jsonFactory;
143 
144         _generatorSettings = (s == null) ? GeneratorSettings.empty
145                 : new GeneratorSettings(null, s, null, null);
146         _prefetch = Prefetch.empty;
147     }
148 
149     /**
150      * Copy constructor used for building variations.
151      */
ObjectWriter(ObjectWriter base, SerializationConfig config, GeneratorSettings genSettings, Prefetch prefetch)152     protected ObjectWriter(ObjectWriter base, SerializationConfig config,
153             GeneratorSettings genSettings, Prefetch prefetch)
154     {
155         _config = config;
156 
157         _serializerProvider = base._serializerProvider;
158         _serializerFactory = base._serializerFactory;
159         _generatorFactory = base._generatorFactory;
160 
161         _generatorSettings = genSettings;
162         _prefetch = prefetch;
163     }
164 
165     /**
166      * Copy constructor used for building variations.
167      */
ObjectWriter(ObjectWriter base, SerializationConfig config)168     protected ObjectWriter(ObjectWriter base, SerializationConfig config)
169     {
170         _config = config;
171 
172         _serializerProvider = base._serializerProvider;
173         _serializerFactory = base._serializerFactory;
174         _generatorFactory = base._generatorFactory;
175 
176         _generatorSettings = base._generatorSettings;
177         _prefetch = base._prefetch;
178     }
179 
180     /**
181      * @since 2.3
182      */
ObjectWriter(ObjectWriter base, JsonFactory f)183     protected ObjectWriter(ObjectWriter base, JsonFactory f)
184     {
185         // may need to override ordering, based on data format capabilities
186         _config = base._config
187             .with(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, f.requiresPropertyOrdering());
188 
189         _serializerProvider = base._serializerProvider;
190         _serializerFactory = base._serializerFactory;
191         _generatorFactory = f;
192 
193         _generatorSettings = base._generatorSettings;
194         _prefetch = base._prefetch;
195     }
196 
197     /**
198      * Method that will return version information stored in and read from jar
199      * that contains this class.
200      */
201     @Override
version()202     public Version version() {
203         return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION;
204     }
205 
206     /*
207     /**********************************************************************
208     /* Internal factory methods, for convenience
209     /**********************************************************************
210      */
211 
212     /**
213      * Overridable factory method called by various "withXxx()" methods
214      *
215      * @since 2.5
216      */
_new(ObjectWriter base, JsonFactory f)217     protected ObjectWriter _new(ObjectWriter base, JsonFactory f) {
218         return new ObjectWriter(base, f);
219     }
220 
221     /**
222      * Overridable factory method called by various "withXxx()" methods
223      *
224      * @since 2.5
225      */
_new(ObjectWriter base, SerializationConfig config)226     protected ObjectWriter _new(ObjectWriter base, SerializationConfig config) {
227         if (config == _config) {
228             return this;
229         }
230         return new ObjectWriter(base, config);
231     }
232 
233     /**
234      * Overridable factory method called by various "withXxx()" methods.
235      * It assumes `this` as base for settings other than those directly
236      * passed in.
237      *
238      * @since 2.5
239      */
_new(GeneratorSettings genSettings, Prefetch prefetch)240     protected ObjectWriter _new(GeneratorSettings genSettings, Prefetch prefetch) {
241         if ((_generatorSettings == genSettings) && (_prefetch == prefetch)) {
242             return this;
243         }
244         return new ObjectWriter(this, _config, genSettings, prefetch);
245     }
246 
247     /**
248      * Overridable factory method called by {@link #writeValues(OutputStream)}
249      * method (and its various overrides), and initializes it as necessary.
250      *
251      * @since 2.5
252      */
253     @SuppressWarnings("resource")
_newSequenceWriter(boolean wrapInArray, JsonGenerator gen, boolean managedInput)254     protected SequenceWriter _newSequenceWriter(boolean wrapInArray,
255             JsonGenerator gen, boolean managedInput)
256         throws IOException
257     {
258         return new SequenceWriter(_serializerProvider(),
259                 _configureGenerator(gen), managedInput, _prefetch)
260             .init(wrapInArray);
261     }
262 
263     /*
264     /**********************************************************
265     /* Life-cycle, fluent factories for SerializationFeature
266     /**********************************************************
267      */
268 
269     /**
270      * Method for constructing a new instance that is configured
271      * with specified feature enabled.
272      */
with(SerializationFeature feature)273     public ObjectWriter with(SerializationFeature feature)  {
274         return _new(this,  _config.with(feature));
275     }
276 
277     /**
278      * Method for constructing a new instance that is configured
279      * with specified features enabled.
280      */
with(SerializationFeature first, SerializationFeature... other)281     public ObjectWriter with(SerializationFeature first, SerializationFeature... other) {
282         return _new(this, _config.with(first, other));
283     }
284 
285     /**
286      * Method for constructing a new instance that is configured
287      * with specified features enabled.
288      */
withFeatures(SerializationFeature... features)289     public ObjectWriter withFeatures(SerializationFeature... features) {
290         return _new(this, _config.withFeatures(features));
291     }
292 
293     /**
294      * Method for constructing a new instance that is configured
295      * with specified feature enabled.
296      */
without(SerializationFeature feature)297     public ObjectWriter without(SerializationFeature feature) {
298         return _new(this, _config.without(feature));
299     }
300 
301     /**
302      * Method for constructing a new instance that is configured
303      * with specified features enabled.
304      */
without(SerializationFeature first, SerializationFeature... other)305     public ObjectWriter without(SerializationFeature first, SerializationFeature... other) {
306         return _new(this, _config.without(first, other));
307     }
308 
309     /**
310      * Method for constructing a new instance that is configured
311      * with specified features enabled.
312      */
withoutFeatures(SerializationFeature... features)313     public ObjectWriter withoutFeatures(SerializationFeature... features) {
314         return _new(this, _config.withoutFeatures(features));
315     }
316 
317     /*
318     /**********************************************************
319     /* Life-cycle, fluent factories for JsonGenerator.Feature (2.5)
320     /**********************************************************
321      */
322 
323     /**
324      * @since 2.5
325      */
with(JsonGenerator.Feature feature)326     public ObjectWriter with(JsonGenerator.Feature feature)  {
327         return _new(this, _config.with(feature));
328     }
329 
330     /**
331      * @since 2.5
332      */
withFeatures(JsonGenerator.Feature... features)333     public ObjectWriter withFeatures(JsonGenerator.Feature... features) {
334         return _new(this, _config.withFeatures(features));
335     }
336 
337     /**
338      * @since 2.5
339      */
without(JsonGenerator.Feature feature)340     public ObjectWriter without(JsonGenerator.Feature feature) {
341         return _new(this, _config.without(feature));
342     }
343 
344     /**
345      * @since 2.5
346      */
withoutFeatures(JsonGenerator.Feature... features)347     public ObjectWriter withoutFeatures(JsonGenerator.Feature... features) {
348         return _new(this, _config.withoutFeatures(features));
349     }
350 
351     /*
352     /**********************************************************
353     /* Life-cycle, fluent factories for StreamWriteFeature (2.11)
354     /**********************************************************
355      */
356 
357     /**
358      * @since 2.11
359      */
with(StreamWriteFeature feature)360     public ObjectWriter with(StreamWriteFeature feature)  {
361         return _new(this, _config.with(feature.mappedFeature()));
362     }
363 
364     /**
365      * @since 2.11
366      */
without(StreamWriteFeature feature)367     public ObjectWriter without(StreamWriteFeature feature) {
368         return _new(this, _config.without(feature.mappedFeature()));
369     }
370 
371     /*
372     /**********************************************************
373     /* Life-cycle, fluent factories for FormatFeature (2.7)
374     /**********************************************************
375      */
376 
377     /**
378      * @since 2.7
379      */
with(FormatFeature feature)380     public ObjectWriter with(FormatFeature feature)  {
381         return _new(this, _config.with(feature));
382     }
383 
384     /**
385      * @since 2.7
386      */
withFeatures(FormatFeature... features)387     public ObjectWriter withFeatures(FormatFeature... features) {
388         return _new(this, _config.withFeatures(features));
389     }
390 
391     /**
392      * @since 2.7
393      */
without(FormatFeature feature)394     public ObjectWriter without(FormatFeature feature) {
395         return _new(this, _config.without(feature));
396     }
397 
398     /**
399      * @since 2.7
400      */
withoutFeatures(FormatFeature... features)401     public ObjectWriter withoutFeatures(FormatFeature... features) {
402         return _new(this, _config.withoutFeatures(features));
403     }
404 
405     /*
406     /**********************************************************
407     /* Life-cycle, fluent factories, type-related
408     /**********************************************************
409      */
410 
411     /**
412      * Method that will construct a new instance that uses specific type
413      * as the root type for serialization, instead of runtime dynamic
414      * type of the root object itself.
415      *<p>
416      * Note that method does NOT change state of this reader, but
417      * rather construct and returns a newly configured instance.
418      *
419      * @since 2.5
420      */
forType(JavaType rootType)421     public ObjectWriter forType(JavaType rootType) {
422         return _new(_generatorSettings, _prefetch.forRootType(this, rootType));
423     }
424 
425     /**
426      * Method that will construct a new instance that uses specific type
427      * as the root type for serialization, instead of runtime dynamic
428      * type of the root object itself.
429      *
430      * @since 2.5
431      */
forType(Class<?> rootType)432     public ObjectWriter forType(Class<?> rootType) {
433         return forType(_config.constructType(rootType));
434     }
435 
436     /**
437      * Method that will construct a new instance that uses specific type
438      * as the root type for serialization, instead of runtime dynamic
439      * type of the root object itself.
440      *
441      * @since 2.5
442      */
forType(TypeReference<?> rootType)443     public ObjectWriter forType(TypeReference<?> rootType) {
444         return forType(_config.getTypeFactory().constructType(rootType.getType()));
445     }
446 
447     /**
448      * @deprecated since 2.5 Use {@link #forType(JavaType)} instead
449      */
450     @Deprecated // since 2.5
withType(JavaType rootType)451     public ObjectWriter withType(JavaType rootType) {
452         return forType(rootType);
453     }
454 
455     /**
456      * @deprecated since 2.5 Use {@link #forType(Class)} instead
457      */
458     @Deprecated // since 2.5
withType(Class<?> rootType)459     public ObjectWriter withType(Class<?> rootType) {
460         return forType(rootType);
461     }
462 
463     /**
464      * @deprecated since 2.5 Use {@link #forType(TypeReference)} instead
465      */
466     @Deprecated // since 2.5
withType(TypeReference<?> rootType)467     public ObjectWriter withType(TypeReference<?> rootType) {
468         return forType(rootType);
469     }
470 
471     /*
472     /**********************************************************
473     /* Life-cycle, fluent factories, other
474     /**********************************************************
475      */
476 
477     /**
478      * Fluent factory method that will construct a new writer instance that will
479      * use specified date format for serializing dates; or if null passed, one
480      * that will serialize dates as numeric timestamps.
481      *<p>
482      * Note that the method does NOT change state of this reader, but
483      * rather construct and returns a newly configured instance.
484      */
with(DateFormat df)485     public ObjectWriter with(DateFormat df) {
486         return _new(this, _config.with(df));
487     }
488 
489     /**
490      * Method that will construct a new instance that will use the default
491      * pretty printer for serialization.
492      */
withDefaultPrettyPrinter()493     public ObjectWriter withDefaultPrettyPrinter() {
494         return with(_config.getDefaultPrettyPrinter());
495     }
496 
497     /**
498      * Method that will construct a new instance that uses specified
499      * provider for resolving filter instances by id.
500      */
with(FilterProvider filterProvider)501     public ObjectWriter with(FilterProvider filterProvider) {
502         if (filterProvider == _config.getFilterProvider()) {
503             return this;
504         }
505         return _new(this, _config.withFilters(filterProvider));
506     }
507 
508     /**
509      * Method that will construct a new instance that will use specified pretty
510      * printer (or, if null, will not do any pretty-printing)
511      */
with(PrettyPrinter pp)512     public ObjectWriter with(PrettyPrinter pp) {
513         return _new(_generatorSettings.with(pp), _prefetch);
514     }
515 
516     /**
517      * Method for constructing a new instance with configuration that
518      * specifies what root name to use for "root element wrapping".
519      * See {@link SerializationConfig#withRootName(String)} for details.
520      *<p>
521      * Note that method does NOT change state of this reader, but
522      * rather construct and returns a newly configured instance.
523      *
524      * @param rootName Root name to use, if non-empty; `null` for "use defaults",
525      *    and empty String ("") for "do NOT add root wrapper"
526      */
withRootName(String rootName)527     public ObjectWriter withRootName(String rootName) {
528         return _new(this, _config.withRootName(rootName));
529     }
530 
531     /**
532      * @since 2.6
533      */
withRootName(PropertyName rootName)534     public ObjectWriter withRootName(PropertyName rootName) {
535         return _new(this, _config.withRootName(rootName));
536     }
537 
538     /**
539      * Convenience method that is same as calling:
540      *<code>
541      *   withRootName("")
542      *</code>
543      * which will forcibly prevent use of root name wrapping when writing
544      * values with this {@link ObjectWriter}.
545      *
546      * @since 2.6
547      */
withoutRootName()548     public ObjectWriter withoutRootName() {
549         return _new(this, _config.withRootName(PropertyName.NO_NAME));
550     }
551 
552     /**
553      * Method that will construct a new instance that uses specific format schema
554      * for serialization.
555      *<p>
556      * Note that method does NOT change state of this reader, but
557      * rather construct and returns a newly configured instance.
558      */
with(FormatSchema schema)559     public ObjectWriter with(FormatSchema schema) {
560         _verifySchemaType(schema);
561         return _new(_generatorSettings.with(schema), _prefetch);
562     }
563 
564     /**
565      * @deprecated Since 2.5 use {@link #with(FormatSchema)} instead
566      */
567     @Deprecated
withSchema(FormatSchema schema)568     public ObjectWriter withSchema(FormatSchema schema) {
569         return with(schema);
570     }
571 
572     /**
573      * Method that will construct a new instance that uses specified
574      * serialization view for serialization (with null basically disables
575      * view processing)
576      *<p>
577      * Note that the method does NOT change state of this reader, but
578      * rather construct and returns a newly configured instance.
579      */
withView(Class<?> view)580     public ObjectWriter withView(Class<?> view) {
581         return _new(this, _config.withView(view));
582     }
583 
with(Locale l)584     public ObjectWriter with(Locale l) {
585         return _new(this, _config.with(l));
586     }
587 
with(TimeZone tz)588     public ObjectWriter with(TimeZone tz) {
589         return _new(this, _config.with(tz));
590     }
591 
592     /**
593      * Method that will construct a new instance that uses specified default
594      * {@link Base64Variant} for base64 encoding
595      *
596      * @since 2.1
597      */
with(Base64Variant b64variant)598     public ObjectWriter with(Base64Variant b64variant) {
599         return _new(this, _config.with(b64variant));
600     }
601 
602     /**
603      * @since 2.3
604      */
with(CharacterEscapes escapes)605     public ObjectWriter with(CharacterEscapes escapes) {
606         return _new(_generatorSettings.with(escapes), _prefetch);
607     }
608 
609     /**
610      * @since 2.3
611      */
with(JsonFactory f)612     public ObjectWriter with(JsonFactory f) {
613         return (f == _generatorFactory) ? this : _new(this, f);
614     }
615 
616     /**
617      * @since 2.3
618      */
with(ContextAttributes attrs)619     public ObjectWriter with(ContextAttributes attrs) {
620         return _new(this, _config.with(attrs));
621     }
622 
623     /**
624      * Mutant factory method that allows construction of a new writer instance
625      * that uses specified set of default attribute values.
626      *
627      * @since 2.3
628      */
withAttributes(Map<?,?> attrs)629     public ObjectWriter withAttributes(Map<?,?> attrs) {
630         return _new(this, _config.withAttributes(attrs));
631     }
632 
633     /**
634      * @since 2.3
635      */
withAttribute(Object key, Object value)636     public ObjectWriter withAttribute(Object key, Object value) {
637         return _new(this, _config.withAttribute(key, value));
638     }
639 
640     /**
641      * @since 2.3
642      */
withoutAttribute(Object key)643     public ObjectWriter withoutAttribute(Object key) {
644         return _new(this, _config.withoutAttribute(key));
645     }
646 
647     /**
648      * @since 2.5
649      */
withRootValueSeparator(String sep)650     public ObjectWriter withRootValueSeparator(String sep) {
651         return _new(_generatorSettings.withRootValueSeparator(sep), _prefetch);
652     }
653 
654     /**
655      * @since 2.5
656      */
withRootValueSeparator(SerializableString sep)657     public ObjectWriter withRootValueSeparator(SerializableString sep) {
658         return _new(_generatorSettings.withRootValueSeparator(sep), _prefetch);
659     }
660 
661     /*
662     /**********************************************************
663     /* Factory methods for creating JsonGenerators (added in 2.11)
664     /**********************************************************
665      */
666 
667     /**
668      * Factory method for constructing properly initialized {@link JsonGenerator}
669      * to write content using specified {@link OutputStream}.
670      * Generator is not managed (or "owned") by ObjectWriter: caller is responsible
671      * for properly closing it once content generation is complete.
672      *
673      * @since 2.11
674      */
createGenerator(OutputStream out)675     public JsonGenerator createGenerator(OutputStream out) throws IOException {
676         _assertNotNull("out", out);
677         return _configureGenerator(_generatorFactory.createGenerator(out, JsonEncoding.UTF8));
678     }
679 
680     /**
681      * Factory method for constructing properly initialized {@link JsonGenerator}
682      * to write content using specified {@link OutputStream} and encoding.
683      * Generator is not managed (or "owned") by ObjectWriter: caller is responsible
684      * for properly closing it once content generation is complete.
685      *
686      * @since 2.11
687      */
createGenerator(OutputStream out, JsonEncoding enc)688     public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
689         _assertNotNull("out", out);
690         return _configureGenerator(_generatorFactory.createGenerator(out, enc));
691     }
692 
693     /**
694      * Factory method for constructing properly initialized {@link JsonGenerator}
695      * to write content using specified {@link Writer}.
696      * Generator is not managed (or "owned") by ObjectWriter: caller is responsible
697      * for properly closing it once content generation is complete.
698      *
699      * @since 2.11
700      */
createGenerator(Writer w)701     public JsonGenerator createGenerator(Writer w) throws IOException {
702         _assertNotNull("w", w);
703         return _configureGenerator(_generatorFactory.createGenerator(w));
704     }
705 
706     /**
707      * Factory method for constructing properly initialized {@link JsonGenerator}
708      * to write content to specified {@link File}, using specified encoding.
709      * Generator is not managed (or "owned") by ObjectWriter: caller is responsible
710      * for properly closing it once content generation is complete.
711      *
712      * @since 2.11
713      */
createGenerator(File outputFile, JsonEncoding enc)714     public JsonGenerator createGenerator(File outputFile, JsonEncoding enc) throws IOException {
715         _assertNotNull("outputFile", outputFile);
716         return _configureGenerator(_generatorFactory.createGenerator(outputFile, enc));
717     }
718 
719     /**
720      * Factory method for constructing properly initialized {@link JsonGenerator}
721      * to write content using specified {@link DataOutput}.
722      * Generator is not managed (or "owned") by ObjectWriter: caller is responsible
723      * for properly closing it once content generation is complete.
724      *
725      * @since 2.11
726      */
createGenerator(DataOutput out)727     public JsonGenerator createGenerator(DataOutput out) throws IOException {
728         _assertNotNull("out", out);
729         return _configureGenerator(_generatorFactory.createGenerator(out));
730     }
731 
732     /*
733     /**********************************************************
734     /* Factory methods for sequence writers (2.5)
735     /**********************************************************
736      */
737 
738     /**
739      * Method for creating a {@link SequenceWriter} to write a sequence of root
740      * values using configuration of this {@link ObjectWriter}.
741      * Sequence is not surrounded by JSON array; some backend types may not
742      * support writing of such sequences as root level.
743      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
744      * values have been written to ensure closing of underlying generator and
745      * output stream.
746      *
747      * @param out Target file to write value sequence to.
748      *
749      * @since 2.5
750      */
writeValues(File out)751     public SequenceWriter writeValues(File out) throws IOException {
752         return _newSequenceWriter(false, createGenerator(out, JsonEncoding.UTF8), true);
753     }
754 
755     /**
756      * Method for creating a {@link SequenceWriter} to write a sequence of root
757      * values using configuration of this {@link ObjectWriter}.
758      * Sequence is not surrounded by JSON array; some backend types may not
759      * support writing of such sequences as root level.
760      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
761      * values have been written to ensure that all content gets flushed by
762      * the generator. However, since a {@link JsonGenerator} is explicitly passed,
763      * it will NOT be closed when {@link SequenceWriter#close()} is called.
764      *
765      * @param g Low-level generator caller has already constructed that will
766      *   be used for actual writing of token stream.
767      *
768      * @since 2.5
769      */
writeValues(JsonGenerator g)770     public SequenceWriter writeValues(JsonGenerator g) throws IOException {
771         _assertNotNull("g", g);
772         return _newSequenceWriter(false, _configureGenerator(g), false);
773     }
774 
775     /**
776      * Method for creating a {@link SequenceWriter} to write a sequence of root
777      * values using configuration of this {@link ObjectWriter}.
778      * Sequence is not surrounded by JSON array; some backend types may not
779      * support writing of such sequences as root level.
780      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
781      * values have been written to ensure closing of underlying generator and
782      * output stream.
783      *
784      * @param out Target writer to use for writing the token stream
785      *
786      * @since 2.5
787      */
writeValues(Writer out)788     public SequenceWriter writeValues(Writer out) throws IOException {
789         return _newSequenceWriter(false, createGenerator(out), true);
790     }
791 
792     /**
793      * Method for creating a {@link SequenceWriter} to write a sequence of root
794      * values using configuration of this {@link ObjectWriter}.
795      * Sequence is not surrounded by JSON array; some backend types may not
796      * support writing of such sequences as root level.
797      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
798      * values have been written to ensure closing of underlying generator and
799      * output stream.
800      *
801      * @param out Physical output stream to use for writing the token stream
802      *
803      * @since 2.5
804      */
writeValues(OutputStream out)805     public SequenceWriter writeValues(OutputStream out) throws IOException {
806         return _newSequenceWriter(false, createGenerator(out, JsonEncoding.UTF8), true);
807     }
808 
809     /**
810      * @since 2.8
811      */
writeValues(DataOutput out)812     public SequenceWriter writeValues(DataOutput out) throws IOException {
813         return _newSequenceWriter(false, createGenerator(out), true);
814     }
815 
816     /**
817      * Method for creating a {@link SequenceWriter} to write an array of
818      * root-level values, using configuration of this {@link ObjectWriter}.
819      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
820      * values have been written to ensure closing of underlying generator and
821      * output stream.
822      *<p>
823      * Note that the type to use with {@link ObjectWriter#forType(Class)} needs to
824      * be type of individual values (elements) to write and NOT matching array
825      * or {@link java.util.Collection} type.
826      *
827      * @param out File to write token stream to
828      *
829      * @since 2.5
830      */
writeValuesAsArray(File out)831     public SequenceWriter writeValuesAsArray(File out) throws IOException {
832         return _newSequenceWriter(true, createGenerator(out, JsonEncoding.UTF8), true);
833     }
834 
835     /**
836      * Method for creating a {@link SequenceWriter} to write an array of
837      * root-level values, using configuration of this {@link ObjectWriter}.
838      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
839      * values have been written to ensure that all content gets flushed by
840      * the generator. However, since a {@link JsonGenerator} is explicitly passed,
841      * it will NOT be closed when {@link SequenceWriter#close()} is called.
842      *<p>
843      * Note that the type to use with {@link ObjectWriter#forType(Class)} needs to
844      * be type of individual values (elements) to write and NOT matching array
845      * or {@link java.util.Collection} type.
846      *
847      * @param gen Underlying generator to use for writing the token stream
848      *
849      * @since 2.5
850      */
writeValuesAsArray(JsonGenerator gen)851     public SequenceWriter writeValuesAsArray(JsonGenerator gen) throws IOException {
852         _assertNotNull("gen", gen);
853         return _newSequenceWriter(true, gen, false);
854     }
855 
856     /**
857      * Method for creating a {@link SequenceWriter} to write an array of
858      * root-level values, using configuration of this {@link ObjectWriter}.
859      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
860      * values have been written to ensure closing of underlying generator and
861      * output stream.
862      *<p>
863      * Note that the type to use with {@link ObjectWriter#forType(Class)} needs to
864      * be type of individual values (elements) to write and NOT matching array
865      * or {@link java.util.Collection} type.
866      *
867      * @param out Writer to use for writing the token stream
868      *
869      * @since 2.5
870      */
writeValuesAsArray(Writer out)871     public SequenceWriter writeValuesAsArray(Writer out) throws IOException {
872         return _newSequenceWriter(true, createGenerator(out), true);
873     }
874 
875     /**
876      * Method for creating a {@link SequenceWriter} to write an array of
877      * root-level values, using configuration of this {@link ObjectWriter}.
878      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
879      * values have been written to ensure closing of underlying generator and
880      * output stream.
881      *<p>
882      * Note that the type to use with {@link ObjectWriter#forType(Class)} needs to
883      * be type of individual values (elements) to write and NOT matching array
884      * or {@link java.util.Collection} type.
885      *
886      * @param out Physical output stream to use for writing the token stream
887      *
888      * @since 2.5
889      */
writeValuesAsArray(OutputStream out)890     public SequenceWriter writeValuesAsArray(OutputStream out) throws IOException {
891         return _newSequenceWriter(true, createGenerator(out, JsonEncoding.UTF8), true);
892     }
893 
894     /**
895      * @since 2.8
896      */
writeValuesAsArray(DataOutput out)897     public SequenceWriter writeValuesAsArray(DataOutput out) throws IOException {
898         return _newSequenceWriter(true, createGenerator(out), true);
899     }
900 
901     /*
902     /**********************************************************
903     /* Simple accessors
904     /**********************************************************
905      */
906 
isEnabled(SerializationFeature f)907     public boolean isEnabled(SerializationFeature f) {
908         return _config.isEnabled(f);
909     }
910 
isEnabled(MapperFeature f)911     public boolean isEnabled(MapperFeature f) {
912         return _config.isEnabled(f);
913     }
914 
915     /**
916      * @since 2.9
917      */
918     @Deprecated
isEnabled(JsonParser.Feature f)919     public boolean isEnabled(JsonParser.Feature f) {
920         return _generatorFactory.isEnabled(f);
921     }
922 
923     /**
924      * @since 2.9
925      */
isEnabled(JsonGenerator.Feature f)926     public boolean isEnabled(JsonGenerator.Feature f) {
927         return _generatorFactory.isEnabled(f);
928     }
929 
930     /**
931      * @since 2.11
932      */
isEnabled(StreamWriteFeature f)933     public boolean isEnabled(StreamWriteFeature f) {
934         return _generatorFactory.isEnabled(f);
935     }
936 
937     /**
938      * @since 2.2
939      */
getConfig()940     public SerializationConfig getConfig() {
941         return _config;
942     }
943 
944     /**
945      * @since 2.2
946      */
getFactory()947     public JsonFactory getFactory() {
948         return _generatorFactory;
949     }
950 
getTypeFactory()951     public TypeFactory getTypeFactory() {
952         return _config.getTypeFactory();
953     }
954 
955     /**
956      * Diagnostics method that can be called to check whether this writer
957      * has pre-fetched serializer to use: pre-fetching improves performance
958      * when writer instances are reused as it avoids a per-call serializer
959      * lookup.
960      *
961      * @since 2.2
962      */
hasPrefetchedSerializer()963     public boolean hasPrefetchedSerializer() {
964         return _prefetch.hasSerializer();
965     }
966 
967     /**
968      * @since 2.3
969      */
getAttributes()970     public ContextAttributes getAttributes() {
971         return _config.getAttributes();
972     }
973 
974     /*
975     /**********************************************************
976     /* Serialization methods; ones from ObjectCodec first
977     /**********************************************************
978      */
979 
980     /**
981      * Method that can be used to serialize any Java value as
982      * JSON output, using provided {@link JsonGenerator}.
983      *<p>
984      * Note that the given {@link JsonGenerator} is not closed; caller
985      * is expected to handle that as necessary.
986      */
writeValue(JsonGenerator g, Object value)987     public void writeValue(JsonGenerator g, Object value) throws IOException
988     {
989         _assertNotNull("g", g);
990         _configureGenerator(g);
991         if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE)
992                 && (value instanceof Closeable)) {
993 
994             Closeable toClose = (Closeable) value;
995             try {
996                 _prefetch.serialize(g, value, _serializerProvider());
997                 if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
998                     g.flush();
999                 }
1000             } catch (Exception e) {
1001                 ClassUtil.closeOnFailAndThrowAsIOE(null, toClose, e);
1002                 return;
1003             }
1004             toClose.close();
1005         } else {
1006             _prefetch.serialize(g, value, _serializerProvider());
1007             if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
1008                 g.flush();
1009             }
1010         }
1011     }
1012 
1013     /*
1014     /**********************************************************
1015     /* Serialization methods, others
1016     /**********************************************************
1017      */
1018 
1019     /**
1020      * Method that can be used to serialize any Java value as
1021      * JSON output, written to File provided.
1022      */
writeValue(File resultFile, Object value)1023     public void writeValue(File resultFile, Object value)
1024         throws IOException, JsonGenerationException, JsonMappingException
1025     {
1026         _writeValueAndClose(createGenerator(resultFile, JsonEncoding.UTF8), value);
1027     }
1028 
1029     /**
1030      * Method that can be used to serialize any Java value as
1031      * JSON output, using output stream provided (using encoding
1032      * {@link JsonEncoding#UTF8}).
1033      *<p>
1034      * Note: method does not close the underlying stream explicitly
1035      * here; however, {@link JsonFactory} this mapper uses may choose
1036      * to close the stream depending on its settings (by default,
1037      * it will try to close it when {@link JsonGenerator} we construct
1038      * is closed).
1039      */
writeValue(OutputStream out, Object value)1040     public void writeValue(OutputStream out, Object value)
1041         throws IOException, JsonGenerationException, JsonMappingException
1042     {
1043         _writeValueAndClose(createGenerator(out, JsonEncoding.UTF8), value);
1044     }
1045 
1046     /**
1047      * Method that can be used to serialize any Java value as
1048      * JSON output, using Writer provided.
1049      *<p>
1050      * Note: method does not close the underlying stream explicitly
1051      * here; however, {@link JsonFactory} this mapper uses may choose
1052      * to close the stream depending on its settings (by default,
1053      * it will try to close it when {@link JsonGenerator} we construct
1054      * is closed).
1055      */
writeValue(Writer w, Object value)1056     public void writeValue(Writer w, Object value)
1057         throws IOException, JsonGenerationException, JsonMappingException
1058     {
1059         _writeValueAndClose(createGenerator(w), value);
1060     }
1061 
1062     /**
1063      * @since 2.8
1064      */
writeValue(DataOutput out, Object value)1065     public void writeValue(DataOutput out, Object value)
1066         throws IOException
1067     {
1068         _writeValueAndClose(createGenerator(out), value);
1069     }
1070 
1071     /**
1072      * Method that can be used to serialize any Java value as
1073      * a String. Functionally equivalent to calling
1074      * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter}
1075      * and constructing String, but more efficient.
1076      *<p>
1077      * Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
1078      */
1079     @SuppressWarnings("resource")
writeValueAsString(Object value)1080     public String writeValueAsString(Object value)
1081         throws JsonProcessingException
1082     {
1083         // alas, we have to pull the recycler directly here...
1084         SegmentedStringWriter sw = new SegmentedStringWriter(_generatorFactory._getBufferRecycler());
1085         try {
1086             _writeValueAndClose(createGenerator(sw), value);
1087         } catch (JsonProcessingException e) {
1088             throw e;
1089         } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
1090             throw JsonMappingException.fromUnexpectedIOE(e);
1091         }
1092         return sw.getAndClear();
1093     }
1094 
1095     /**
1096      * Method that can be used to serialize any Java value as
1097      * a byte array. Functionally equivalent to calling
1098      * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream}
1099      * and getting bytes, but more efficient.
1100      * Encoding used will be UTF-8.
1101      *<p>
1102      * Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
1103      */
1104     @SuppressWarnings("resource")
writeValueAsBytes(Object value)1105     public byte[] writeValueAsBytes(Object value)
1106         throws JsonProcessingException
1107     {
1108         ByteArrayBuilder bb = new ByteArrayBuilder(_generatorFactory._getBufferRecycler());
1109         try {
1110             _writeValueAndClose(createGenerator(bb, JsonEncoding.UTF8), value);
1111         } catch (JsonProcessingException e) { // to support [JACKSON-758]
1112             throw e;
1113         } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
1114             throw JsonMappingException.fromUnexpectedIOE(e);
1115         }
1116         byte[] result = bb.toByteArray();
1117         bb.release();
1118         return result;
1119     }
1120 
1121     /*
1122     /**********************************************************
1123     /* Other public methods
1124     /**********************************************************
1125      */
1126 
1127     /**
1128      * Method for visiting type hierarchy for given type, using specified visitor.
1129      * Visitation uses <code>Serializer</code> hierarchy and related properties
1130      *<p>
1131      * This method can be used for things like
1132      * generating <a href="http://json-schema.org/">Json Schema</a>
1133      * instance for specified type.
1134      *
1135      * @param type Type to generate schema for (possibly with generic signature)
1136      *
1137      * @since 2.2
1138      */
acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor)1139     public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException
1140     {
1141         _assertNotNull("type", type);
1142         _assertNotNull("visitor", visitor);
1143         _serializerProvider().acceptJsonFormatVisitor(type, visitor);
1144     }
1145 
1146     /**
1147      * Since 2.6
1148      */
acceptJsonFormatVisitor(Class<?> type, JsonFormatVisitorWrapper visitor)1149     public void acceptJsonFormatVisitor(Class<?> type, JsonFormatVisitorWrapper visitor) throws JsonMappingException {
1150         _assertNotNull("type", type);
1151         _assertNotNull("visitor", visitor);
1152         acceptJsonFormatVisitor(_config.constructType(type), visitor);
1153     }
1154 
canSerialize(Class<?> type)1155     public boolean canSerialize(Class<?> type) {
1156         _assertNotNull("type", type);
1157         return _serializerProvider().hasSerializerFor(type, null);
1158     }
1159 
1160     /**
1161      * Method for checking whether instances of given type can be serialized,
1162      * and optionally why (as per {@link Throwable} returned).
1163      *
1164      * @since 2.3
1165      */
canSerialize(Class<?> type, AtomicReference<Throwable> cause)1166     public boolean canSerialize(Class<?> type, AtomicReference<Throwable> cause) {
1167         _assertNotNull("type", type);
1168         return _serializerProvider().hasSerializerFor(type, cause);
1169     }
1170 
1171     /*
1172     /**********************************************************
1173     /* Overridable helper methods
1174     /**********************************************************
1175      */
1176 
1177     /**
1178      * Overridable helper method used for constructing
1179      * {@link SerializerProvider} to use for serialization.
1180      */
_serializerProvider()1181     protected DefaultSerializerProvider _serializerProvider() {
1182         return _serializerProvider.createInstance(_config, _serializerFactory);
1183     }
1184 
1185     /*
1186     /**********************************************************
1187     /* Internal methods
1188     /**********************************************************
1189      */
1190 
1191     /**
1192      * @since 2.2
1193      */
_verifySchemaType(FormatSchema schema)1194     protected void _verifySchemaType(FormatSchema schema)
1195     {
1196         if (schema != null) {
1197             if (!_generatorFactory.canUseSchema(schema)) {
1198                     throw new IllegalArgumentException("Cannot use FormatSchema of type "+schema.getClass().getName()
1199                             +" for format "+_generatorFactory.getFormatName());
1200             }
1201         }
1202     }
1203 
1204     /**
1205      * Method called to configure the generator as necessary and then
1206      * call write functionality
1207      *
1208      * @since 2.11.2
1209      */
_writeValueAndClose(JsonGenerator gen, Object value)1210     protected final void _writeValueAndClose(JsonGenerator gen, Object value) throws IOException
1211     {
1212         if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
1213             _writeCloseable(gen, value);
1214             return;
1215         }
1216         try {
1217             _prefetch.serialize(gen, value, _serializerProvider());
1218         } catch (Exception e) {
1219             ClassUtil.closeOnFailAndThrowAsIOE(gen, e);
1220             return;
1221         }
1222         gen.close();
1223     }
1224 
1225     /**
1226      * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
1227      * method is to be called right after serialization has been called
1228      */
_writeCloseable(JsonGenerator gen, Object value)1229     private final void _writeCloseable(JsonGenerator gen, Object value)
1230         throws IOException
1231     {
1232         Closeable toClose = (Closeable) value;
1233         try {
1234             _prefetch.serialize(gen, value, _serializerProvider());
1235             Closeable tmpToClose = toClose;
1236             toClose = null;
1237             tmpToClose.close();
1238         } catch (Exception e) {
1239             ClassUtil.closeOnFailAndThrowAsIOE(gen, toClose, e);
1240             return;
1241         }
1242         gen.close();
1243     }
1244 
1245     /**
1246      * Helper method called to set or override settings of passed-in
1247      * {@link JsonGenerator}
1248      *
1249      * @since 2.5
1250      */
_configureGenerator(JsonGenerator gen)1251     protected final JsonGenerator _configureGenerator(JsonGenerator gen)
1252     {
1253         // order is slightly significant: both may change PrettyPrinter
1254         // settings.
1255         _config.initialize(gen); // since 2.5
1256         _generatorSettings.initialize(gen);
1257         return gen;
1258     }
1259 
_assertNotNull(String paramName, Object src)1260     protected final void _assertNotNull(String paramName, Object src) {
1261         if (src == null) {
1262             throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
1263         }
1264     }
1265 
1266     /*
1267     /**********************************************************
1268     /* Helper classes for configuration
1269     /**********************************************************
1270      */
1271 
1272     /**
1273      * Helper class used for containing settings specifically related
1274      * to (re)configuring {@link JsonGenerator} constructed for
1275      * writing output.
1276      *
1277      * @since 2.5
1278      */
1279     public final static class GeneratorSettings
1280         implements java.io.Serializable
1281     {
1282         private static final long serialVersionUID = 1L;
1283 
1284         public final static GeneratorSettings empty = new GeneratorSettings(null, null, null, null);
1285 
1286         /**
1287          * To allow for dynamic enabling/disabling of pretty printing,
1288          * pretty printer can be optionally configured for writer
1289          * as well
1290          */
1291         public final PrettyPrinter prettyPrinter;
1292 
1293         /**
1294          * When using data format that uses a schema, schema is passed
1295          * to generator.
1296          */
1297         public final FormatSchema schema;
1298 
1299         /**
1300          * Caller may want to specify character escaping details, either as
1301          * defaults, or on call-by-call basis.
1302          */
1303         public final CharacterEscapes characterEscapes;
1304 
1305         /**
1306          * Caller may want to override so-called "root value separator",
1307          * String added (verbatim, with no quoting or escaping) between
1308          * values in root context. Default value is a single space character,
1309          * but this is often changed to linefeed.
1310          */
1311         public final SerializableString rootValueSeparator;
1312 
GeneratorSettings(PrettyPrinter pp, FormatSchema sch, CharacterEscapes esc, SerializableString rootSep)1313         public GeneratorSettings(PrettyPrinter pp, FormatSchema sch,
1314                 CharacterEscapes esc, SerializableString rootSep) {
1315             prettyPrinter = pp;
1316             schema = sch;
1317             characterEscapes = esc;
1318             rootValueSeparator = rootSep;
1319         }
1320 
with(PrettyPrinter pp)1321         public GeneratorSettings with(PrettyPrinter pp) {
1322             // since null would mean "don't care", need to use placeholder to indicate "disable"
1323             if (pp == null) {
1324                 pp = NULL_PRETTY_PRINTER;
1325             }
1326             return (pp == prettyPrinter) ? this
1327                     : new GeneratorSettings(pp, schema, characterEscapes, rootValueSeparator);
1328         }
1329 
with(FormatSchema sch)1330         public GeneratorSettings with(FormatSchema sch) {
1331             return (schema == sch) ? this
1332                     : new GeneratorSettings(prettyPrinter, sch, characterEscapes, rootValueSeparator);
1333         }
1334 
with(CharacterEscapes esc)1335         public GeneratorSettings with(CharacterEscapes esc) {
1336             return (characterEscapes == esc) ? this
1337                     : new GeneratorSettings(prettyPrinter, schema, esc, rootValueSeparator);
1338         }
1339 
withRootValueSeparator(String sep)1340         public GeneratorSettings withRootValueSeparator(String sep) {
1341             if (sep == null) {
1342                 if (rootValueSeparator == null) {
1343                     return this;
1344                 }
1345                 return new GeneratorSettings(prettyPrinter, schema, characterEscapes, null);
1346             }
1347             if (sep.equals(_rootValueSeparatorAsString())) {
1348                 return this;
1349             }
1350             return new GeneratorSettings(prettyPrinter, schema, characterEscapes,
1351                     new SerializedString(sep));
1352         }
1353 
withRootValueSeparator(SerializableString sep)1354         public GeneratorSettings withRootValueSeparator(SerializableString sep) {
1355             if (sep == null) {
1356                 if (rootValueSeparator == null) {
1357                     return this;
1358                 }
1359                 return new GeneratorSettings(prettyPrinter, schema, characterEscapes, null);
1360             }
1361             if (sep.equals(rootValueSeparator)) {
1362                 return this;
1363             }
1364             return new GeneratorSettings(prettyPrinter, schema, characterEscapes, sep);
1365         }
1366 
_rootValueSeparatorAsString()1367         private final String _rootValueSeparatorAsString() {
1368             return (rootValueSeparator == null) ? null : rootValueSeparator.getValue();
1369         }
1370 
1371         /**
1372          * @since 2.6
1373          */
initialize(JsonGenerator gen)1374         public void initialize(JsonGenerator gen)
1375         {
1376             PrettyPrinter pp = prettyPrinter;
1377             if (prettyPrinter != null) {
1378                 if (pp == NULL_PRETTY_PRINTER) {
1379                     gen.setPrettyPrinter(null);
1380                 } else {
1381                     if (pp instanceof Instantiatable<?>) {
1382                         pp = (PrettyPrinter) ((Instantiatable<?>) pp).createInstance();
1383                     }
1384                     gen.setPrettyPrinter(pp);
1385                 }
1386             }
1387             if (characterEscapes != null) {
1388                 gen.setCharacterEscapes(characterEscapes);
1389             }
1390             if (schema != null) {
1391                 gen.setSchema(schema);
1392             }
1393             if (rootValueSeparator != null) {
1394                 gen.setRootValueSeparator(rootValueSeparator);
1395             }
1396         }
1397     }
1398 
1399     /**
1400      * As a minor optimization, we will make an effort to pre-fetch a serializer,
1401      * or at least relevant <code>TypeSerializer</code>, if given enough
1402      * information.
1403      *
1404      * @since 2.5
1405      */
1406     public final static class Prefetch
1407         implements java.io.Serializable
1408     {
1409         private static final long serialVersionUID = 1L;
1410 
1411         public final static Prefetch empty = new Prefetch(null, null, null);
1412 
1413         /**
1414          * Specified root serialization type to use; can be same
1415          * as runtime type, but usually one of its super types
1416          * (parent class or interface it implements).
1417          */
1418         private final JavaType rootType;
1419 
1420         /**
1421          * We may pre-fetch serializer if {@link #rootType}
1422          * is known, and if so, reuse it afterwards.
1423          * This allows avoiding further serializer lookups and increases
1424          * performance a bit on cases where readers are reused.
1425          */
1426         private final JsonSerializer<Object> valueSerializer;
1427 
1428         /**
1429          * When dealing with polymorphic types, we cannot pre-fetch
1430          * serializer, but can pre-fetch {@link TypeSerializer}.
1431          */
1432         private final TypeSerializer typeSerializer;
1433 
Prefetch(JavaType rootT, JsonSerializer<Object> ser, TypeSerializer typeSer)1434         private Prefetch(JavaType rootT,
1435                 JsonSerializer<Object> ser, TypeSerializer typeSer)
1436         {
1437             rootType = rootT;
1438             valueSerializer = ser;
1439             typeSerializer = typeSer;
1440         }
1441 
forRootType(ObjectWriter parent, JavaType newType)1442         public Prefetch forRootType(ObjectWriter parent, JavaType newType) {
1443             // First: if nominal type not defined not thing much to do
1444             if (newType == null) {
1445                 if ((rootType == null) || (valueSerializer == null)) {
1446                     return this;
1447                 }
1448                 return new Prefetch(null, null, null);
1449             }
1450 
1451             // Second: if no change, nothing to do either
1452             if (newType.equals(rootType)) {
1453                 return this;
1454             }
1455 
1456             // But one more trick: `java.lang.Object` has no serialized, but may
1457             // have `TypeSerializer` to use
1458             if (newType.isJavaLangObject()) {
1459                 DefaultSerializerProvider prov = parent._serializerProvider();
1460                 TypeSerializer typeSer;
1461 
1462                 try {
1463                     typeSer = prov.findTypeSerializer(newType);
1464                 } catch (JsonMappingException e) {
1465                     // Unlike with value serializer pre-fetch, let's not allow exception
1466                     // for TypeSerializer be swallowed
1467                     throw new RuntimeJsonMappingException(e);
1468                 }
1469                 return new Prefetch(null, null, typeSer);
1470             }
1471 
1472             if (parent.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)) {
1473                 DefaultSerializerProvider prov = parent._serializerProvider();
1474                 // 17-Dec-2014, tatu: Need to be bit careful here; TypeSerializers are NOT cached,
1475                 //   so although it'd seem like a good idea to look for those first, and avoid
1476                 //   serializer for polymorphic types, it is actually more efficient to do the
1477                 //   reverse here.
1478                 try {
1479                     JsonSerializer<Object> ser = prov.findTypedValueSerializer(newType, true, null);
1480                     // Important: for polymorphic types, "unwrap"...
1481                     if (ser instanceof TypeWrappedSerializer) {
1482                         return new Prefetch(newType, null,
1483                                 ((TypeWrappedSerializer) ser).typeSerializer());
1484                     }
1485                     return new Prefetch(newType, ser, null);
1486                 } catch (JsonMappingException e) {
1487                     // need to swallow?
1488                     ;
1489                 }
1490             }
1491             return new Prefetch(newType, null, typeSerializer);
1492         }
1493 
getValueSerializer()1494         public final JsonSerializer<Object> getValueSerializer() {
1495             return valueSerializer;
1496         }
1497 
getTypeSerializer()1498         public final TypeSerializer getTypeSerializer() {
1499             return typeSerializer;
1500         }
1501 
hasSerializer()1502         public boolean hasSerializer() {
1503             return (valueSerializer != null) || (typeSerializer != null);
1504         }
1505 
serialize(JsonGenerator gen, Object value, DefaultSerializerProvider prov)1506         public void serialize(JsonGenerator gen, Object value, DefaultSerializerProvider prov)
1507             throws IOException
1508         {
1509             if (typeSerializer != null) {
1510                 prov.serializePolymorphic(gen, value, rootType, valueSerializer, typeSerializer);
1511             } else  if (valueSerializer != null) {
1512                 prov.serializeValue(gen, value, rootType, valueSerializer);
1513             } else if (rootType != null) {
1514                 prov.serializeValue(gen, value, rootType);
1515             } else {
1516                 prov.serializeValue(gen, value);
1517             }
1518         }
1519     }
1520 }
1521