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      */

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, nullnullnull);
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      */

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      */

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, nullnull);
146         _prefetch = Prefetch.empty;
147     }
148     
149     /**
150      * Copy constructor used for building variations.
151      */

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      */

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      */

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
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      */

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      */

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      */

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")
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      */

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      */

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      */

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      */

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      */

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      */

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      */

326     public ObjectWriter with(JsonGenerator.Feature feature)  {
327         return _new(this, _config.with(feature));
328     }
329
330     /**
331      * @since 2.5
332      */

333     public ObjectWriter withFeatures(JsonGenerator.Feature... features) {
334         return _new(this, _config.withFeatures(features));
335     }
336
337     /**
338      * @since 2.5
339      */

340     public ObjectWriter without(JsonGenerator.Feature feature) {
341         return _new(this, _config.without(feature));
342     }
343
344     /**
345      * @since 2.5
346      */

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      */

360     public ObjectWriter with(StreamWriteFeature feature)  {
361         return _new(this, _config.with(feature.mappedFeature()));
362     }
363
364     /**
365      * @since 2.11
366      */

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      */

380     public ObjectWriter with(FormatFeature feature)  {
381         return _new(this, _config.with(feature));
382     }
383
384     /**
385      * @since 2.7
386      */

387     public ObjectWriter withFeatures(FormatFeature... features) {
388         return _new(this, _config.withFeatures(features));
389     }
390
391     /**
392      * @since 2.7
393      */

394     public ObjectWriter without(FormatFeature feature) {
395         return _new(this, _config.without(feature));
396     }
397
398     /**
399      * @since 2.7
400      */

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      */

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      */

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      */

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
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
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
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      */

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      */

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      */

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      */

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; `nullfor "use defaults",
525      *    and empty String (""for "do NOT add root wrapper"
526      */

527     public ObjectWriter withRootName(String rootName) {
528         return _new(this, _config.withRootName(rootName));
529     }
530
531     /**
532      * @since 2.6
533      */

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      */

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      */

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
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      */

580     public ObjectWriter withView(Class<?> view) {
581         return _new(this, _config.withView(view));
582     }    
583
584     public ObjectWriter with(Locale l) {
585         return _new(this, _config.with(l));
586     }
587
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      */

598     public ObjectWriter with(Base64Variant b64variant) {
599         return _new(this, _config.with(b64variant));
600     }
601
602     /**
603      * @since 2.3
604      */

605     public ObjectWriter with(CharacterEscapes escapes) {
606         return _new(_generatorSettings.with(escapes), _prefetch);
607     }
608
609     /**
610      * @since 2.3
611      */

612     public ObjectWriter with(JsonFactory f) {
613         return (f == _generatorFactory) ? this : _new(this, f);
614     }    
615
616     /**
617      * @since 2.3
618      */

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      */

629     public ObjectWriter withAttributes(Map<?,?> attrs) {
630         return _new(this, _config.withAttributes(attrs));
631     }
632
633     /**
634      * @since 2.3
635      */

636     public ObjectWriter withAttribute(Object key, Object value) {
637         return _new(this, _config.withAttribute(key, value));
638     }
639
640     /**
641      * @since 2.3
642      */

643     public ObjectWriter withoutAttribute(Object key) {
644         return _new(this, _config.withoutAttribute(key));
645     }
646
647     /**
648      * @since 2.5
649      */

650     public ObjectWriter withRootValueSeparator(String sep) {
651         return _new(_generatorSettings.withRootValueSeparator(sep), _prefetch);
652     }
653
654     /**
655      * @since 2.5
656      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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
907     public boolean isEnabled(SerializationFeature f) {
908         return _config.isEnabled(f);
909     }
910
911     public boolean isEnabled(MapperFeature f) {
912         return _config.isEnabled(f);
913     }
914
915     /**
916      * @since 2.9
917      */

918     @Deprecated
919     public boolean isEnabled(JsonParser.Feature f) {
920         return _generatorFactory.isEnabled(f);
921     }
922
923     /**
924      * @since 2.9
925      */

926     public boolean isEnabled(JsonGenerator.Feature f) {
927         return _generatorFactory.isEnabled(f);
928     }
929
930     /**
931      * @since 2.11
932      */

933     public boolean isEnabled(StreamWriteFeature f) {
934         return _generatorFactory.isEnabled(f);
935     }
936
937     /**
938      * @since 2.2
939      */

940     public SerializationConfig getConfig() {
941         return _config;
942     }
943
944     /**
945      * @since 2.2
946      */

947     public JsonFactory getFactory() {
948         return _generatorFactory;
949     }
950     
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      */

963     public boolean hasPrefetchedSerializer() {
964         return _prefetch.hasSerializer();
965     }
966
967     /**
968      * @since 2.3
969      */

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      */

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      */

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      */

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      */

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      */

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")
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")
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      */

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      */

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
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      */

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      */

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      */

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      */

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      */

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      */

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
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(nullnullnullnull);
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
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
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
1330         public GeneratorSettings with(FormatSchema sch) {
1331             return (schema == sch) ? this
1332                     : new GeneratorSettings(prettyPrinter, sch, characterEscapes, rootValueSeparator);
1333         }
1334
1335         public GeneratorSettings with(CharacterEscapes esc) {
1336             return (characterEscapes == esc) ? this
1337                     : new GeneratorSettings(prettyPrinter, schema, esc, rootValueSeparator);
1338         }
1339
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
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
1367         private final String _rootValueSeparatorAsString() {
1368             return (rootValueSeparator == null) ? null : rootValueSeparator.getValue();
1369         }
1370
1371         /**
1372          * @since 2.6
1373          */

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(nullnullnull);
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         
1434         private Prefetch(JavaType rootT,
1435                 JsonSerializer<Object> ser, TypeSerializer typeSer)
1436         {
1437             rootType = rootT;
1438             valueSerializer = ser;
1439             typeSerializer = typeSer;
1440         }
1441
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(nullnullnull);
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(nullnull, 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, truenull);
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
1494         public final JsonSerializer<Object> getValueSerializer() {
1495             return valueSerializer;
1496         }
1497
1498         public final TypeSerializer getTypeSerializer() {
1499             return typeSerializer;
1500         }
1501
1502         public boolean hasSerializer() {
1503             return (valueSerializer != null) || (typeSerializer != null);
1504         }
1505
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