1 /* Jackson JSON-processor.
2  *
3  * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi
4  */

5 package com.fasterxml.jackson.core;
6
7 import java.io.*;
8 import java.math.BigDecimal;
9 import java.math.BigInteger;
10 import java.util.concurrent.atomic.AtomicBoolean;
11 import java.util.concurrent.atomic.AtomicInteger;
12 import java.util.concurrent.atomic.AtomicLong;
13
14 import com.fasterxml.jackson.core.JsonParser.NumberType;
15 import com.fasterxml.jackson.core.io.CharacterEscapes;
16 import com.fasterxml.jackson.core.type.WritableTypeId;
17 import com.fasterxml.jackson.core.type.WritableTypeId.Inclusion;
18 import com.fasterxml.jackson.core.util.VersionUtil;
19
20 import static com.fasterxml.jackson.core.JsonTokenId.*;
21
22 /**
23  * Base class that defines public API for writing JSON content.
24  * Instances are created using factory methods of
25  * a {@link JsonFactory} instance.
26  *
27  * @author Tatu Saloranta
28  */

29 public abstract class JsonGenerator
30     implements Closeable, Flushable, Versioned
31 {
32     /**
33      * Enumeration that defines all togglable features for generators.
34      */

35     public enum Feature {
36         // // Low-level I/O / content features
37
38         /**
39          * Feature that determines whether generator will automatically
40          * close underlying output target that is NOT owned by the
41          * generator.
42          * If disabled, calling application has to separately
43          * close the underlying {@link OutputStream} and {@link Writer}
44          * instances used to create the generator. If enabled, generator
45          * will handle closing, as long as generator itself gets closed:
46          * this happens when end-of-input is encountered, or generator
47          * is closed by a call to {@link JsonGenerator#close}.
48          *<p>
49          * Feature is enabled by default.
50          */

51         AUTO_CLOSE_TARGET(true),
52
53         /**
54          * Feature that determines what happens when the generator is
55          * closed while there are still unmatched
56          * {@link JsonToken#START_ARRAY} or {@link JsonToken#START_OBJECT}
57          * entries in output content. If enabled, such Array(s) and/or
58          * Object(s) are automatically closed; if disabled, nothing
59          * specific is done.
60          *<p>
61          * Feature is enabled by default.
62          */

63         AUTO_CLOSE_JSON_CONTENT(true),
64
65         /**
66          * Feature that specifies that calls to {@link #flush} will cause
67          * matching <code>flush()</code> to underlying {@link OutputStream}
68          * or {@link Writer}; if disabled this will not be done.
69          * Main reason to disable this feature is to prevent flushing at
70          * generator level, if it is not possible to prevent method being
71          * called by other code (like <code>ObjectMapper</code> or third
72          * party libraries).
73          *<p>
74          * Feature is enabled by default.
75          */

76         FLUSH_PASSED_TO_STREAM(true),
77
78         // // Quoting-related features
79         
80         /**
81          * Feature that determines whether JSON Object field names are
82          * quoted using double-quotes, as specified by JSON specification
83          * or not. Ability to disable quoting was added to support use
84          * cases where they are not usually expected, which most commonly
85          * occurs when used straight from Javascript.
86          *<p>
87          * Feature is enabled by default (since it is required by JSON specification).
88          *
89          * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#QUOTE_FIELD_NAMES} instead
90          */

91         @Deprecated
92         QUOTE_FIELD_NAMES(true),
93
94         /**
95          * Feature that determines whether "exceptional" (not real number)
96          * float/double values are output as quoted strings.
97          * The values checked are Double.Nan,
98          * Double.POSITIVE_INFINITY and Double.NEGATIVE_INIFINTY (and 
99          * associated Float values).
100          * If feature is disabled, these numbers are still output using
101          * associated literal values, resulting in non-conformant
102          * output.
103          *<p>
104          * Feature is enabled by default.
105          *
106          * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#WRITE_NAN_AS_STRINGS} instead
107          */

108          @Deprecated
109         QUOTE_NON_NUMERIC_NUMBERS(true),
110
111         // // Character escaping features
112
113         /**
114          * Feature that specifies that all characters beyond 7-bit ASCII
115          * range (i.e. code points of 128 and above) need to be output
116          * using format-specific escapes (for JSON, backslash escapes),
117          * if format uses escaping mechanisms (which is generally true
118          * for textual formats but not for binary formats).
119          *<p>
120          * Note that this setting may not necessarily make sense for all
121          * data formats (for example, binary formats typically do not use
122          * any escaping mechanisms; and some textual formats do not have
123          * general-purpose escaping); if so, settings is simply ignored.
124          * Put another way, effects of this feature are data-format specific.
125          *<p>
126          * Feature is disabled by default.
127          *
128          * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#ESCAPE_NON_ASCII} instead
129          */

130         @Deprecated
131         ESCAPE_NON_ASCII(false),
132
133         // // Datatype coercion features
134
135         /**
136          * Feature that forces all Java numbers to be written as Strings,
137          * even if the underlying data format has non-textual representation
138          * (which is the case for JSON as well as all binary formats).
139          * Default state is 'false', meaning that Java numbers are to
140          * be serialized using basic numeric serialization (as JSON
141          * numbers, integral or floating point, for example).
142          * If enabled, all such numeric values are instead written out as
143          * textual values (which for JSON means quoted in double-quotes).
144          *<p>
145          * One use case is to avoid problems with Javascript limitations:
146          * since Javascript standard specifies that all number handling
147          * should be done using 64-bit IEEE 754 floating point values,
148          * result being that some 64-bit integer values can not be
149          * accurately represent (as mantissa is only 51 bit wide).
150          *<p>
151          * Feature is disabled by default.
152          *
153          * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#WRITE_NUMBERS_AS_STRINGS} instead
154          */

155         @Deprecated
156         WRITE_NUMBERS_AS_STRINGS(false),
157
158         /**
159          * Feature that determines whether {@link java.math.BigDecimal} entries are
160          * serialized using {@link java.math.BigDecimal#toPlainString()} to prevent
161          * values to be written using scientific notation.
162          *<p>
163          * NOTE: only affects generators that serialize {@link java.math.BigDecimal}s
164          * using textual representation (textual formats but potentially some binary
165          * formats).
166          *<p>
167          * Feature is disabled by default, so default output mode is used; this generally
168          * depends on how {@link BigDecimal} has been created.
169          * 
170          * @since 2.3
171          */

172         WRITE_BIGDECIMAL_AS_PLAIN(false),
173
174         // // Schema/Validity support features
175
176         /**
177          * Feature that determines whether {@link JsonGenerator} will explicitly
178          * check that no duplicate JSON Object field names are written.
179          * If enabled, generator will check all names within context and report
180          * duplicates by throwing a {@link JsonGenerationException}; if disabled,
181          * no such checking will be done. Assumption in latter case is
182          * that caller takes care of not trying to write duplicate names.
183          *<p>
184          * Note that enabling this feature will incur performance overhead
185          * due to having to store and check additional information.
186          *<p>
187          * Feature is disabled by default.
188          * 
189          * @since 2.3
190          */

191         STRICT_DUPLICATE_DETECTION(false),
192         
193         /**
194          * Feature that determines what to do if the underlying data format requires knowledge
195          * of all properties to output, and if no definition is found for a property that
196          * caller tries to write. If enabled, such properties will be quietly ignored;
197          * if disabled, a {@link JsonProcessingException} will be thrown to indicate the
198          * problem.
199          * Typically most textual data formats do NOT require schema information (although
200          * some do, such as CSV), whereas many binary data formats do require definitions
201          * (such as Avro, protobuf), although not all (Smile, CBOR, BSON and MessagePack do not).
202          *<p>
203          * Note that support for this feature is implemented by individual data format
204          * module, if (and only if) it makes sense for the format in question. For JSON,
205          * for example, this feature has no effect as properties need not be pre-defined.
206          *<p>
207          * Feature is disabled by default, meaning that if the underlying data format
208          * requires knowledge of all properties to output, attempts to write an unknown
209          * property will result in a {@link JsonProcessingException}
210          *
211          * @since 2.5
212          */

213         IGNORE_UNKNOWN(false),
214         ;
215
216         private final boolean _defaultState;
217         private final int _mask;
218         
219         /**
220          * Method that calculates bit set (flags) of all features that
221          * are enabled by default.
222          */

223         public static int collectDefaults()
224         {
225             int flags = 0;
226             for (Feature f : values()) {
227                 if (f.enabledByDefault()) {
228                     flags |= f.getMask();
229                 }
230             }
231             return flags;
232         }
233         
234         private Feature(boolean defaultState) {
235             _defaultState = defaultState;
236             _mask = (1 << ordinal());
237         }
238
239         public boolean enabledByDefault() { return _defaultState; }
240
241         /**
242          * @since 2.3
243          */

244         public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
245
246         public int getMask() { return _mask; }
247     }
248
249     /*
250     /**********************************************************
251     /* Configuration
252     /**********************************************************
253      */

254
255     /**
256      * Object that handles pretty-printing (usually additional
257      * white space to make results more human-readable) during
258      * output. If null, no pretty-printing is done.
259      */

260     protected PrettyPrinter _cfgPrettyPrinter;
261
262     /*
263     /**********************************************************
264     /* Construction, initialization
265     /**********************************************************
266      */

267     
268     protected JsonGenerator() { }
269
270     /**
271      * Method that can be called to set or reset the object to
272      * use for writing Java objects as JsonContent
273      * (using method {@link #writeObject}).
274      *
275      * @return Generator itself (this), to allow chaining
276      */

277     public abstract JsonGenerator setCodec(ObjectCodec oc);
278
279     /**
280      * Method for accessing the object used for writing Java
281      * object as JSON content
282      * (using method {@link #writeObject}).
283      */

284     public abstract ObjectCodec getCodec();
285
286     /**
287      * Accessor for finding out version of the bundle that provided this generator instance.
288      */

289     @Override
290     public abstract Version version();
291
292     /*
293     /**********************************************************
294     /* Public API, Feature configuration
295     /**********************************************************
296      */

297
298     /**
299      * Method for enabling specified parser features:
300      * check {@link Feature} for list of available features.
301      *
302      * @return Generator itself (this), to allow chaining
303      */

304     public abstract JsonGenerator enable(Feature f);
305
306     /**
307      * Method for disabling specified  features
308      * (check {@link Feature} for list of features)
309      *
310      * @return Generator itself (this), to allow chaining
311      */

312     public abstract JsonGenerator disable(Feature f);
313
314     /**
315      * Method for enabling or disabling specified feature:
316      * check {@link Feature} for list of available features.
317      *
318      * @return Generator itself (this), to allow chaining
319      */

320     public final JsonGenerator configure(Feature f, boolean state) {
321         if (state) enable(f); else disable(f);
322         return this;
323     }
324
325     /**
326      * Method for checking whether given feature is enabled.
327      * Check {@link Feature} for list of available features.
328      */

329     public abstract boolean isEnabled(Feature f);
330
331     /**
332      * @since 2.10
333      */

334     public boolean isEnabled(StreamWriteFeature f) {
335         return isEnabled(f.mappedFeature());
336     }
337
338     /**
339      * Bulk access method for getting state of all standard (non-dataformat-specific)
340      * {@link JsonGenerator.Feature}s.
341      * 
342      * @return Bit mask that defines current states of all standard {@link JsonGenerator.Feature}s.
343      * 
344      * @since 2.3
345      */

346     public abstract int getFeatureMask();
347
348     /**
349      * Bulk set method for (re)setting states of all standard {@link Feature}s
350      * 
351      * @since 2.3
352      * 
353      * @param values Bitmask that defines which {@link Feature}s are enabled
354      *    and which disabled
355      *
356      * @return This parser object, to allow chaining of calls
357      *
358      * @deprecated Since 2.7, use {@link #overrideStdFeatures(intint)} instead -- remove from 2.9
359      */

360     @Deprecated
361     public abstract JsonGenerator setFeatureMask(int values);
362
363     /**
364      * Bulk set method for (re)setting states of features specified by <code>mask</code>.
365      * Functionally equivalent to
366      *<code>
367      *    int oldState = getFeatureMask();
368      *    int newState = (oldState &amp; ~mask) | (values &amp; mask);
369      *    setFeatureMask(newState);
370      *</code>
371      * but preferred as this lets caller more efficiently specify actual changes made.
372      * 
373      * @param values Bit mask of set/clear state for features to change
374      * @param mask Bit mask of features to change
375      * 
376      * @since 2.6
377      */

378     public JsonGenerator overrideStdFeatures(int values, int mask) {
379         int oldState = getFeatureMask();
380         int newState = (oldState & ~mask) | (values & mask);
381         return setFeatureMask(newState);
382     }
383
384     /**
385      * Bulk access method for getting state of all {@link FormatFeature}s, format-specific
386      * on/off configuration settings.
387      * 
388      * @return Bit mask that defines current states of all standard {@link FormatFeature}s.
389      * 
390      * @since 2.6
391      */

392     public int getFormatFeatures() {
393         return 0;
394     }
395     
396     /**
397      * Bulk set method for (re)setting states of {@link FormatFeature}s,
398      * by specifying values (set / clear) along with a mask, to determine
399      * which features to change, if any.
400      *<p>
401      * Default implementation will simply throw an exception to indicate that
402      * the generator implementation does not support any {@link FormatFeature}s.
403      * 
404      * @param values Bit mask of set/clear state for features to change
405      * @param mask Bit mask of features to change
406      * 
407      * @since 2.6
408      */

409     public JsonGenerator overrideFormatFeatures(int values, int mask) {
410         // 08-Oct-2018, tatu: For 2.10 we actually do get `JsonWriteFeature`s, although they
411         //    are (for 2.x only, not for 3.x) mapper to legacy settings. So do not freak out:
412 //        throw new IllegalArgumentException("No FormatFeatures defined for generator of type "+getClass().getName());
413         return this;
414     }
415     
416     /*
417     /**********************************************************
418     /* Public API, Schema configuration
419     /**********************************************************
420      */

421
422     /**
423      * Method to call to make this generator use specified schema.
424      * Method must be called before generating any content, right after instance
425      * has been created.
426      * Note that not all generators support schemas; and those that do usually only
427      * accept specific types of schemas: ones defined for data format this generator
428      * produces.
429      *<p>
430      * If generator does not support specified schema, {@link UnsupportedOperationException}
431      * is thrown.
432      * 
433      * @param schema Schema to use
434      * 
435      * @throws UnsupportedOperationException if generator does not support schema
436      */

437     public void setSchema(FormatSchema schema) {
438         throw new UnsupportedOperationException(String.format(
439                 "Generator of type %s does not support schema of type '%s'",
440                 getClass().getName(), schema.getSchemaType()));
441     }
442
443     /**
444      * Method for accessing Schema that this parser uses, if any.
445      * Default implementation returns null.
446      *
447      * @since 2.1
448      */

449     public FormatSchema getSchema() { return null; }
450
451     /*
452     /**********************************************************
453     /* Public API, other configuration
454     /**********************************************************
455       */

456
457     /**
458      * Method for setting a custom pretty printer, which is usually
459      * used to add indentation for improved human readability.
460      * By default, generator does not do pretty printing.
461      *<p>
462      * To use the default pretty printer that comes with core
463      * Jackson distribution, call {@link #useDefaultPrettyPrinter}
464      * instead.
465      *
466      * @return Generator itself (this), to allow chaining
467      */

468     public JsonGenerator setPrettyPrinter(PrettyPrinter pp) {
469         _cfgPrettyPrinter = pp;
470         return this;
471     }
472
473     /**
474      * Accessor for checking whether this generator has a configured
475      * {@link PrettyPrinter}; returns it if so, null if none configured.
476      * 
477      * @since 2.1
478      */

479     public PrettyPrinter getPrettyPrinter() {
480         return _cfgPrettyPrinter;
481     }
482     
483     /**
484      * Convenience method for enabling pretty-printing using
485      * the default pretty printer
486      * ({@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter}).
487      *
488      * @return Generator itself (this), to allow chaining
489      */

490     public abstract JsonGenerator useDefaultPrettyPrinter();
491
492     /**
493      * Method that can be called to request that generator escapes
494      * all character codes above specified code point (if positive value);
495      * or, to not escape any characters except for ones that must be
496      * escaped for the data format (if -1).
497      * To force escaping of all non-ASCII characters, for example,
498      * this method would be called with value of 127.
499      *<p>
500      * Note that generators are NOT required to support setting of value
501      * higher than 127, because there are other ways to affect quoting
502      * (or lack thereof) of character codes between 0 and 127.
503      * Not all generators support concept of escaping, either; if so,
504      * calling this method will have no effect.
505      *<p>
506      * Default implementation does nothing; sub-classes need to redefine
507      * it according to rules of supported data format.
508      * 
509      * @param charCode Either -1 to indicate that no additional escaping
510      *   is to be done; or highest code point not to escape (meaning higher
511      *   ones will be), if positive value.
512      */

513     public JsonGenerator setHighestNonEscapedChar(int charCode) { return this; }
514
515     /**
516      * Accessor method for testing what is the highest unescaped character
517      * configured for this generator. This may be either positive value
518      * (when escaping configuration has been set and is in effect), or
519      * 0 to indicate that no additional escaping is in effect.
520      * Some generators may not support additional escaping: for example,
521      * generators for binary formats that do not use escaping should
522      * simply return 0.
523      * 
524      * @return Currently active limitation for highest non-escaped character,
525      *   if defined; or 0 to indicate no additional escaping is performed.
526      */

527     public int getHighestEscapedChar() { return 0; }
528
529     /**
530      * Method for accessing custom escapes factory uses for {@link JsonGenerator}s
531      * it creates.
532      */

533     public CharacterEscapes getCharacterEscapes() { return null; }
534
535     /**
536      * Method for defining custom escapes factory uses for {@link JsonGenerator}s
537      * it creates.
538      *<p>
539      * Default implementation does nothing and simply returns this instance.
540      */

541     public JsonGenerator setCharacterEscapes(CharacterEscapes esc) { return this; }
542
543     /**
544      * Method that allows overriding String used for separating root-level
545      * JSON values (default is single space character)
546      *<p>
547      * Default implementation throws {@link UnsupportedOperationException}.
548      * 
549      * @param sep Separator to use, if any; null means that no separator is
550      *   automatically added
551      * 
552      * @since 2.1
553      */

554     public JsonGenerator setRootValueSeparator(SerializableString sep) {
555         throw new UnsupportedOperationException();
556     }
557
558     /*
559     /**********************************************************
560     /* Public API, output state access
561     /**********************************************************
562      */

563     
564     /**
565      * Method that can be used to get access to object that is used
566      * as target for generated output; this is usually either
567      * {@link OutputStream} or {@link Writer}, depending on what
568      * generator was constructed with.
569      * Note that returned value may be null in some cases; including
570      * case where implementation does not want to exposed raw
571      * source to caller.
572      * In cases where output has been decorated, object returned here
573      * is the decorated version; this allows some level of interaction
574      * between users of generator and decorator object.
575      *<p>
576      * In general use of this accessor should be considered as
577      * "last effort", i.e. only used if no other mechanism is applicable.
578      */

579     public Object getOutputTarget() {
580         return null;
581     }
582
583     /**
584      * Method for verifying amount of content that is buffered by generator
585      * but not yet flushed to the underlying target (stream, writer),
586      * in units (bytechar) that the generator implementation uses for buffering;
587      * or -1 if this information is not available.
588      * Unit used is often the same as the unit of underlying target (that is,
589      * `bytefor {@link java.io.OutputStream}, `charfor {@link java.io.Writer}),
590      * but may differ if buffering is done before encoding.
591      * Default JSON-backed implementations do use matching units.
592      *<p>
593      * Note: non-JSON implementations will be retrofitted for 2.6 and beyond;
594      * please report if you see -1 (missing override)
595      *
596      * @return Amount of content buffered in internal units, if amount known and
597      *    accessible; -1 if not accessible.
598      *
599      * @since 2.6
600      */

601     public int getOutputBuffered() {
602         return -1;
603     }
604
605     /**
606      * Helper method, usually equivalent to:
607      *<code>
608      *   getOutputContext().getCurrentValue();
609      *</code>
610      *<p>
611      * Note that "current value" is NOT populated (or used) by Streaming parser;
612      * it is only used by higher-level data-binding functionality.
613      * The reason it is included here is that it can be stored and accessed hierarchically,
614      * and gets passed through data-binding.
615      * 
616      * @since 2.5
617      */

618     public Object getCurrentValue() {
619         JsonStreamContext ctxt = getOutputContext();
620         return (ctxt == null) ? null : ctxt.getCurrentValue();
621     }
622
623     /**
624      * Helper method, usually equivalent to:
625      *<code>
626      *   getOutputContext().setCurrentValue(v);
627      *</code>
628      * 
629      * @since 2.5
630      */

631     public void setCurrentValue(Object v) {
632         JsonStreamContext ctxt = getOutputContext();
633         if (ctxt != null) {
634             ctxt.setCurrentValue(v);
635         }
636     }
637     
638     /*
639     /**********************************************************
640     /* Public API, capability introspection methods
641     /**********************************************************
642      */

643
644     /**
645      * Method that can be used to verify that given schema can be used with
646      * this generator (using {@link #setSchema}).
647      * 
648      * @param schema Schema to check
649      * 
650      * @return True if this generator can use given schema; false if not
651      */

652     public boolean canUseSchema(FormatSchema schema) { return false; }
653     
654     /**
655      * Introspection method that may be called to see if the underlying
656      * data format supports some kind of Object Ids natively (many do not;
657      * for example, JSON doesn't).
658      * This method <b>must</b> be called prior to calling
659      * {@link #writeObjectId} or {@link #writeObjectRef}.
660      *<p>
661      * Default implementation returns false; overridden by data formats
662      * that do support native Object Ids. Caller is expected to either
663      * use a non-native notation (explicit property or such), or fail,
664      * in case it can not use native object ids.
665      * 
666      * @since 2.3
667      */

668     public boolean canWriteObjectId() { return false; }
669
670     /**
671      * Introspection method that may be called to see if the underlying
672      * data format supports some kind of Type Ids natively (many do not;
673      * for example, JSON doesn't).
674      * This method <b>must</b> be called prior to calling
675      * {@link #writeTypeId}.
676      *<p>
677      * Default implementation returns false; overridden by data formats
678      * that do support native Type Ids. Caller is expected to either
679      * use a non-native notation (explicit property or such), or fail,
680      * in case it can not use native type ids.
681      * 
682      * @since 2.3
683      */

684     public boolean canWriteTypeId() { return false; }
685
686     /**
687      * Introspection method that may be called to see if the underlying
688      * data format supports "native" binary data; that is, an efficient
689      * output of binary content without encoding.
690      *<p>
691      * Default implementation returns false; overridden by data formats
692      * that do support native binary content.
693      * 
694      * @since 2.3
695      */

696     public boolean canWriteBinaryNatively() { return false; }
697     
698     /**
699      * Introspection method to call to check whether it is ok to omit
700      * writing of Object fields or not. Most formats do allow omission,
701      * but certain positional formats (such as CSV) require output of
702      * placeholders, even if no real values are to be emitted.
703      * 
704      * @since 2.3
705      */

706     public boolean canOmitFields() { return true; }
707
708     /**
709      * Introspection method to call to check whether it is possible
710      * to write numbers using {@link #writeNumber(java.lang.String)}
711      * using possible custom format, or not. Typically textual formats
712      * allow this (and JSON specifically does), whereas binary formats
713      * do not allow this (except by writing them as Strings).
714      * Usual reason for calling this method is to check whether custom
715      * formatting of numbers may be applied by higher-level code (databinding)
716      * or not.
717      *
718      * @since 2.8
719      */

720     public boolean canWriteFormattedNumbers() { return false; }
721
722     /*
723     /**********************************************************
724     /* Public API, write methods, structural
725     /**********************************************************
726      */

727
728     /**
729      * Method for writing starting marker of a Array value
730      * (for JSON this is character '['; plus possible white space decoration
731      * if pretty-printing is enabled).
732      *<p>
733      * Array values can be written in any context where values
734      * are allowed: meaning everywhere except for when
735      * a field name is expected.
736      */

737     public abstract void writeStartArray() throws IOException;
738
739     // TODO: deprecate in 2.11 (remove from 3.0)
740     /**
741      * Method for writing start marker of an Array value, similar
742      * to {@link #writeStartArray()}, but also specifying how many
743      * elements will be written for the array before calling
744      * {@link #writeEndArray()}.
745      *<p>
746      * Default implementation simply calls {@link #writeStartArray()}.
747      * 
748      * @param size Number of elements this array will have: actual
749      *   number of values written (before matching call to
750      *   {@link #writeEndArray()} MUST match; generator MAY verify
751      *   this is the case.
752      *   
753      * @since 2.4
754      */

755     public void writeStartArray(int size) throws IOException {
756         writeStartArray();
757     }
758
759     /**
760      * @since 2.10
761      */

762     public void writeStartArray(Object forValue) throws IOException {
763         writeStartArray();
764         setCurrentValue(forValue);
765     }
766
767     /**
768      * @since 2.10
769      */

770     public void writeStartArray(Object forValue, int size) throws IOException {
771         writeStartArray(size);
772         setCurrentValue(forValue);
773     }
774
775     /**
776      * Method for writing closing marker of a JSON Array value
777      * (character ']'; plus possible white space decoration
778      * if pretty-printing is enabled).
779      *<p>
780      * Marker can be written if the innermost structured type
781      * is Array.
782      */

783     public abstract void writeEndArray() throws IOException;
784
785     /**
786      * Method for writing starting marker of an Object value
787      * (character '{'; plus possible white space decoration
788      * if pretty-printing is enabled).
789      *<p>
790      * Object values can be written in any context where values
791      * are allowed: meaning everywhere except for when
792      * a field name is expected.
793      */

794     public abstract void writeStartObject() throws IOException;
795
796     /**
797      * Method for writing starting marker of an Object value
798      * to represent the given Java Object value.
799      * Argument is offered as metadata, but more
800      * importantly it should be assigned as the "current value"
801      * for the Object content that gets constructed and initialized.
802      *<p>
803      * Object values can be written in any context where values
804      * are allowed: meaning everywhere except for when
805      * a field name is expected.
806      *
807      * @since 2.8
808      */

809     public void writeStartObject(Object forValue) throws IOException
810     {
811         writeStartObject();
812         setCurrentValue(forValue);
813     }
814
815     /**
816      * Method for writing starting marker of an Object value
817      * to represent the given Java Object value.
818      * Argument is offered as metadata, but more
819      * importantly it should be assigned as the "current value"
820      * for the Object content that gets constructed and initialized.
821      * In addition, caller knows number of key/value pairs ("properties")
822      * that will get written for the Object value: this is relevant for
823      * some format backends (but not, as an example, for JSON).
824      *<p>
825      * Object values can be written in any context where values
826      * are allowed: meaning everywhere except for when
827      * a field name is expected.
828      *
829      * @since 2.10
830      */

831     public void writeStartObject(Object forValue, int size) throws IOException
832     {
833         writeStartObject();
834         setCurrentValue(forValue);
835     }
836
837     /**
838      * Method for writing closing marker of an Object value
839      * (character '}'; plus possible white space decoration
840      * if pretty-printing is enabled).
841      *<p>
842      * Marker can be written if the innermost structured type
843      * is Object, and the last written event was either a
844      * complete value, or START-OBJECT marker (see JSON specification
845      * for more details).
846      */

847     public abstract void writeEndObject() throws IOException;
848
849     /**
850      * Method for writing a field name (JSON String surrounded by
851      * double quotes: syntactically identical to a JSON String value),
852      * possibly decorated by white space if pretty-printing is enabled.
853      *<p>
854      * Field names can only be written in Object context (check out
855      * JSON specification for details), when field name is expected
856      * (field names alternate with values).
857      */

858     public abstract void writeFieldName(String name) throws IOException;
859
860     /**
861      * Method similar to {@link #writeFieldName(String)}, main difference
862      * being that it may perform better as some of processing (such as
863      * quoting of certain characters, or encoding into external encoding
864      * if supported by generator) can be done just once and reused for
865      * later calls.
866      *<p>
867      * Default implementation simple uses unprocessed name container in
868      * serialized String; implementations are strongly encouraged to make
869      * use of more efficient methods argument object has.
870      */

871     public abstract void writeFieldName(SerializableString name) throws IOException;
872
873     /**
874      * Alternative to {@link #writeFieldName(String)} that may be used
875      * in cases where property key is of numeric type; either where
876      * underlying format supports such notion (some binary formats do,
877      * unlike JSON), or for convenient conversion into String presentation.
878      * Default implementation will simply convert id into <code>String</code>
879      * and call {@link #writeFieldName(String)}.
880      *
881      * @since 2.8
882      */

883     public void writeFieldId(long id) throws IOException {
884         writeFieldName(Long.toString(id));
885     }
886
887     /*
888     /**********************************************************
889     /* Public API, write methods, scalar arrays (2.8)
890     /**********************************************************
891      */

892
893     /**
894      * Value write method that can be called to write a single
895      * array (sequence of {@link JsonToken#START_ARRAY}, zero or
896      * more {@link JsonToken#VALUE_NUMBER_INT}, {@link JsonToken#END_ARRAY})
897      *
898      * @since 2.8
899      *
900      * @param array Array that contains values to write
901      * @param offset Offset of the first element to write, within array
902      * @param length Number of elements in array to write, from `offset` to `offset + len - 1`
903      */

904     public void writeArray(int[] array, int offset, int length) throws IOException
905     {
906         if (array == null) {
907             throw new IllegalArgumentException("null array");
908         }
909         _verifyOffsets(array.length, offset, length);
910         writeStartArray(array, length);
911         for (int i = offset, end = offset+length; i < end; ++i) {
912             writeNumber(array[i]);
913         }
914         writeEndArray();
915     }
916
917     /**
918      * Value write method that can be called to write a single
919      * array (sequence of {@link JsonToken#START_ARRAY}, zero or
920      * more {@link JsonToken#VALUE_NUMBER_INT}, {@link JsonToken#END_ARRAY})
921      *
922      * @since 2.8
923      *
924      * @param array Array that contains values to write
925      * @param offset Offset of the first element to write, within array
926      * @param length Number of elements in array to write, from `offset` to `offset + len - 1`
927      */

928     public void writeArray(long[] array, int offset, int length) throws IOException
929     {
930         if (array == null) {
931             throw new IllegalArgumentException("null array");
932         }
933         _verifyOffsets(array.length, offset, length);
934         writeStartArray(array, length);
935         for (int i = offset, end = offset+length; i < end; ++i) {
936             writeNumber(array[i]);
937         }
938         writeEndArray();
939     }
940
941     /**
942      * Value write method that can be called to write a single
943      * array (sequence of {@link JsonToken#START_ARRAY}, zero or
944      * more {@link JsonToken#VALUE_NUMBER_FLOAT}, {@link JsonToken#END_ARRAY})
945      *
946      * @since 2.8
947      *
948      * @param array Array that contains values to write
949      * @param offset Offset of the first element to write, within array
950      * @param length Number of elements in array to write, from `offset` to `offset + len - 1`
951      */

952     public void writeArray(double[] array, int offset, int length) throws IOException
953     {
954         if (array == null) {
955             throw new IllegalArgumentException("null array");
956         }
957         _verifyOffsets(array.length, offset, length);
958         writeStartArray(array, length);
959         for (int i = offset, end = offset+length; i < end; ++i) {
960             writeNumber(array[i]);
961         }
962         writeEndArray();
963     }
964
965     /**
966      * Value write method that can be called to write a single
967      * array (sequence of {@link JsonToken#START_ARRAY}, zero or
968      * more {@link JsonToken#VALUE_STRING}, {@link JsonToken#END_ARRAY})
969      *
970      * @since 2.11
971      *
972      * @param array Array that contains values to write
973      * @param offset Offset of the first element to write, within array
974      * @param length Number of elements in array to write, from `offset` to `offset + len - 1`
975      */

976     public void writeArray(String[] array, int offset, int length) throws IOException
977     {
978         if (array == null) {
979             throw new IllegalArgumentException("null array");
980         }
981         _verifyOffsets(array.length, offset, length);
982         writeStartArray(array, length);
983         for (int i = offset, end = offset+length; i < end; ++i) {
984             writeString(array[i]);
985         }
986         writeEndArray();
987     }
988
989     /*
990     /**********************************************************
991     /* Public API, write methods, text/String values
992     /**********************************************************
993      */

994
995     /**
996      * Method for outputting a String value. Depending on context
997      * this means either array element, (object) field value or
998      * a stand alone String; but in all cases, String will be
999      * surrounded in double quotes, and contents will be properly
1000      * escaped as required by JSON specification.
1001      */

1002     public abstract void writeString(String text) throws IOException;
1003
1004     /**
1005      * Method for outputting a String value. Depending on context
1006      * this means either array element, (object) field value or
1007      * a stand alone String; but in all cases, String will be
1008      * surrounded in double quotes, and contents will be properly
1009      * escaped as required by JSON specification.
1010      * If the reader is null, then write a null.
1011      * If len is &lt; 0, then write all contents of the reader.
1012      * Otherwise, write only len characters.
1013      *
1014      * @since 2.9
1015      */

1016     public void writeString(Reader reader, int len) throws IOException {
1017         // Let's implement this as "unsupported" to make it easier to add new parser impls
1018         _reportUnsupportedOperation();
1019     }
1020
1021     /**
1022      * Method for outputting a String value. Depending on context
1023      * this means either array element, (object) field value or
1024      * a stand alone String; but in all cases, String will be
1025      * surrounded in double quotes, and contents will be properly
1026      * escaped as required by JSON specification.
1027      */

1028     public abstract void writeString(char[] text, int offset, int len) throws IOException;
1029
1030     /**
1031      * Method similar to {@link #writeString(String)}, but that takes
1032      * {@link SerializableString} which can make this potentially
1033      * more efficient to call as generator may be able to reuse
1034      * quoted and/or encoded representation.
1035      *<p>
1036      * Default implementation just calls {@link #writeString(String)};
1037      * sub-classes should override it with more efficient implementation
1038      * if possible.
1039      */

1040     public abstract void writeString(SerializableString text) throws IOException;
1041
1042     /**
1043      * Method similar to {@link #writeString(String)} but that takes as
1044      * its input a UTF-8 encoded String that is to be output as-is, without additional
1045      * escaping (type of which depends on data format; backslashes for JSON).
1046      * However, quoting that data format requires (like double-quotes for JSON) will be added
1047      * around the value if and as necessary.
1048      *<p>
1049      * Note that some backends may choose not to support this method: for
1050      * example, if underlying destination is a {@link java.io.Writer}
1051      * using this method would require UTF-8 decoding.
1052      * If so, implementation may instead choose to throw a
1053      * {@link UnsupportedOperationException} due to ineffectiveness
1054      * of having to decode input.
1055      */

1056     public abstract void writeRawUTF8String(byte[] text, int offset, int length)
1057         throws IOException;
1058
1059     /**
1060      * Method similar to {@link #writeString(String)} but that takes as its input
1061      * a UTF-8 encoded String which has <b>not</b> been escaped using whatever
1062      * escaping scheme data format requires (for JSON that is backslash-escaping
1063      * for control characters and double-quotes; for other formats something else).
1064      * This means that textual JSON backends need to check if value needs
1065      * JSON escaping, but otherwise can just be copied as is to output.
1066      * Also, quoting that data format requires (like double-quotes for JSON) will be added
1067      * around the value if and as necessary.
1068      *<p>
1069      * Note that some backends may choose not to support this method: for
1070      * example, if underlying destination is a {@link java.io.Writer}
1071      * using this method would require UTF-8 decoding.
1072      * In this case
1073      * generator implementation may instead choose to throw a
1074      * {@link UnsupportedOperationException} due to ineffectiveness
1075      * of having to decode input.
1076      */

1077     public abstract void writeUTF8String(byte[] text, int offset, int length)
1078         throws IOException;
1079
1080     /*
1081     /**********************************************************
1082     /* Public API, write methods, binary/raw content
1083     /**********************************************************
1084      */

1085
1086     /**
1087      * Method that will force generator to copy
1088      * input text verbatim with <b>no</b> modifications (including
1089      * that no escaping is done and no separators are added even
1090      * if context [array, object] would otherwise require such).
1091      * If such separators are desired, use
1092      * {@link #writeRawValue(String)} instead.
1093      *<p>
1094      * Note that not all generator implementations necessarily support
1095      * such by-pass methods: those that do not will throw
1096      * {@link UnsupportedOperationException}.
1097      */

1098     public abstract void writeRaw(String text) throws IOException;
1099
1100     /**
1101      * Method that will force generator to copy
1102      * input text verbatim with <b>no</b> modifications (including
1103      * that no escaping is done and no separators are added even
1104      * if context [array, object] would otherwise require such).
1105      * If such separators are desired, use
1106      * {@link #writeRawValue(String)} instead.
1107      *<p>
1108      * Note that not all generator implementations necessarily support
1109      * such by-pass methods: those that do not will throw
1110      * {@link UnsupportedOperationException}.
1111      */

1112     public abstract void writeRaw(String text, int offset, int len) throws IOException;
1113
1114     /**
1115      * Method that will force generator to copy
1116      * input text verbatim with <b>no</b> modifications (including
1117      * that no escaping is done and no separators are added even
1118      * if context [array, object] would otherwise require such).
1119      * If such separators are desired, use
1120      * {@link #writeRawValue(String)} instead.
1121      *<p>
1122      * Note that not all generator implementations necessarily support
1123      * such by-pass methods: those that do not will throw
1124      * {@link UnsupportedOperationException}.
1125      */

1126     public abstract void writeRaw(char[] text, int offset, int len) throws IOException;
1127
1128     /**
1129      * Method that will force generator to copy
1130      * input text verbatim with <b>no</b> modifications (including
1131      * that no escaping is done and no separators are added even
1132      * if context [array, object] would otherwise require such).
1133      * If such separators are desired, use
1134      * {@link #writeRawValue(String)} instead.
1135      *<p>
1136      * Note that not all generator implementations necessarily support
1137      * such by-pass methods: those that do not will throw
1138      * {@link UnsupportedOperationException}.
1139      */

1140     public abstract void writeRaw(char c) throws IOException;
1141
1142     /**
1143      * Method that will force generator to copy
1144      * input text verbatim with <b>no</b> modifications (including
1145      * that no escaping is done and no separators are added even
1146      * if context [array, object] would otherwise require such).
1147      * If such separators are desired, use
1148      * {@link #writeRawValue(String)} instead.
1149      *<p>
1150      * Note that not all generator implementations necessarily support
1151      * such by-pass methods: those that do not will throw
1152      * {@link UnsupportedOperationException}.
1153      *<p>
1154      * The default implementation delegates to {@link #writeRaw(String)};
1155      * other backends that support raw inclusion of text are encouraged
1156      * to implement it in more efficient manner (especially if they
1157      * use UTF-8 encoding).
1158      * 
1159      * @since 2.1
1160      */

1161 //    public abstract void writeRaw(SerializableString raw) throws IOException;
1162     public void writeRaw(SerializableString raw) throws IOException {
1163         writeRaw(raw.getValue());
1164     }
1165
1166     /**
1167      * Method that will force generator to copy
1168      * input text verbatim without any modifications, but assuming
1169      * it must constitute a single legal JSON value (number, string,
1170      * booleannull, Array or List). Assuming this, proper separators
1171      * are added if and as needed (comma or colon), and generator
1172      * state updated to reflect this.
1173      */

1174     public abstract void writeRawValue(String text) throws IOException;
1175
1176     public abstract void writeRawValue(String text, int offset, int len) throws IOException;
1177
1178     public abstract void writeRawValue(char[] text, int offset, int len) throws IOException;
1179
1180     /**
1181      * Method similar to {@link #writeRawValue(String)}, but potentially more
1182      * efficient as it may be able to use pre-encoded content (similar to
1183      * {@link #writeRaw(SerializableString)}.
1184      * 
1185      * @since 2.5
1186      */

1187     public void writeRawValue(SerializableString raw) throws IOException {
1188         writeRawValue(raw.getValue());
1189     }
1190
1191     /**
1192      * Method that will output given chunk of binary data as base64
1193      * encoded, as a complete String value (surrounded by double quotes).
1194      * This method defaults
1195      *<p>
1196      * Note: because JSON Strings can not contain unescaped linefeeds,
1197      * if linefeeds are included (as per last argument), they must be
1198      * escaped. This adds overhead for decoding without improving
1199      * readability.
1200      * Alternatively if linefeeds are not included,
1201      * resulting String value may violate the requirement of base64
1202      * RFC which mandates line-length of 76 characters and use of
1203      * linefeeds. However, all {@link JsonParser} implementations
1204      * are required to accept such "long line base64"; as do
1205      * typical production-level base64 decoders.
1206      *
1207      * @param bv Base64 variant to use: defines details such as
1208      *   whether padding is used (and if so, using which character);
1209      *   what is the maximum line length before adding linefeed,
1210      *   and also the underlying alphabet to use.
1211      */

1212     public abstract void writeBinary(Base64Variant bv,
1213             byte[] data, int offset, int len) throws IOException;
1214
1215     /**
1216      * Similar to {@link #writeBinary(Base64Variant,byte[],int,int)},
1217      * but default to using the Jackson default Base64 variant 
1218      * (which is {@link Base64Variants#MIME_NO_LINEFEEDS}).
1219      */

1220     public void writeBinary(byte[] data, int offset, int len) throws IOException {
1221         writeBinary(Base64Variants.getDefaultVariant(), data, offset, len);
1222     }
1223
1224     /**
1225      * Similar to {@link #writeBinary(Base64Variant,byte[],int,int)},
1226      * but assumes default to using the Jackson default Base64 variant 
1227      * (which is {@link Base64Variants#MIME_NO_LINEFEEDS}). Also
1228      * assumes that whole byte array is to be output.
1229      */

1230     public void writeBinary(byte[] data) throws IOException {
1231         writeBinary(Base64Variants.getDefaultVariant(), data, 0, data.length);
1232     }
1233
1234     /**
1235      * Similar to {@link #writeBinary(Base64Variant,InputStream,int)},
1236      * but assumes default to using the Jackson default Base64 variant 
1237      * (which is {@link Base64Variants#MIME_NO_LINEFEEDS}).
1238      * 
1239      * @param data InputStream to use for reading binary data to write.
1240      *    Will not be closed after successful write operation
1241      * @param dataLength (optional) number of bytes that will be available;
1242      *    or -1 to be indicate it is not known. Note that implementations
1243      *    need not support cases where length is not known in advance; this
1244      *    depends on underlying data format: JSON output does NOT require length,
1245      *    other formats may
1246      */

1247     public int writeBinary(InputStream data, int dataLength)
1248         throws IOException {
1249         return writeBinary(Base64Variants.getDefaultVariant(), data, dataLength);
1250     }
1251     
1252     /**
1253      * Method similar to {@link #writeBinary(Base64Variant,byte[],int,int)},
1254      * but where input is provided through a stream, allowing for incremental
1255      * writes without holding the whole input in memory.
1256      * 
1257      * @param bv Base64 variant to use
1258      * @param data InputStream to use for reading binary data to write.
1259      *    Will not be closed after successful write operation
1260      * @param dataLength (optional) number of bytes that will be available;
1261      *    or -1 to be indicate it is not known.
1262      *    If a positive length is given, <code>data</code> MUST provide at least
1263      *    that many bytes: if not, an exception will be thrown.
1264      *    Note that implementations
1265      *    need not support cases where length is not known in advance; this
1266      *    depends on underlying data format: JSON output does NOT require length,
1267      *    other formats may.
1268      * 
1269      * @return Number of bytes read from <code>data</code> and written as binary payload
1270      * 
1271      * @since 2.1
1272      */

1273     public abstract int writeBinary(Base64Variant bv,
1274             InputStream data, int dataLength) throws IOException;
1275
1276     /*
1277     /**********************************************************
1278     /* Public API, write methods, numeric
1279     /**********************************************************
1280      */

1281
1282     /**
1283      * Method for outputting given value as JSON number.
1284      * Can be called in any context where a value is expected
1285      * (Array value, Object field value, root-level value).
1286      * Additional white space may be added around the value
1287      * if pretty-printing is enabled.
1288      *
1289      * @param v Number value to write
1290      *
1291      * @since 2.2
1292      */

1293     public void writeNumber(short v) throws IOException { writeNumber((int) v); }
1294
1295     /**
1296      * Method for outputting given value as JSON number.
1297      * Can be called in any context where a value is expected
1298      * (Array value, Object field value, root-level value).
1299      * Additional white space may be added around the value
1300      * if pretty-printing is enabled.
1301      *
1302      * @param v Number value to write
1303      */

1304     public abstract void writeNumber(int v) throws IOException;
1305
1306     /**
1307      * Method for outputting given value as JSON number.
1308      * Can be called in any context where a value is expected
1309      * (Array value, Object field value, root-level value).
1310      * Additional white space may be added around the value
1311      * if pretty-printing is enabled.
1312      *
1313      * @param v Number value to write
1314      */

1315     public abstract void writeNumber(long v) throws IOException;
1316
1317     /**
1318      * Method for outputting given value as JSON number.
1319      * Can be called in any context where a value is expected
1320      * (Array value, Object field value, root-level value).
1321      * Additional white space may be added around the value
1322      * if pretty-printing is enabled.
1323      *
1324      * @param v Number value to write
1325      */

1326     public abstract void writeNumber(BigInteger v) throws IOException;
1327
1328     /**
1329      * Method for outputting indicate JSON numeric value.
1330      * Can be called in any context where a value is expected
1331      * (Array value, Object field value, root-level value).
1332      * Additional white space may be added around the value
1333      * if pretty-printing is enabled.
1334      *
1335      * @param v Number value to write
1336      */

1337     public abstract void writeNumber(double v) throws IOException;
1338
1339     /**
1340      * Method for outputting indicate JSON numeric value.
1341      * Can be called in any context where a value is expected
1342      * (Array value, Object field value, root-level value).
1343      * Additional white space may be added around the value
1344      * if pretty-printing is enabled.
1345      *
1346      * @param v Number value to write
1347      */

1348     public abstract void writeNumber(float v) throws IOException;
1349
1350     /**
1351      * Method for outputting indicate JSON numeric value.
1352      * Can be called in any context where a value is expected
1353      * (Array value, Object field value, root-level value).
1354      * Additional white space may be added around the value
1355      * if pretty-printing is enabled.
1356      *
1357      * @param v Number value to write
1358      */

1359     public abstract void writeNumber(BigDecimal v) throws IOException;
1360
1361     /**
1362      * Write method that can be used for custom numeric types that can
1363      * not be (easily?) converted to "standard" Java number types.
1364      * Because numbers are not surrounded by double quotes, regular
1365      * {@link #writeString} method can not be used; nor
1366      * {@link #writeRaw} because that does not properly handle
1367      * value separators needed in Array or Object contexts.
1368      *<p>
1369      * Note: because of lack of type safety, some generator
1370      * implementations may not be able to implement this
1371      * method. For example, if a binary JSON format is used,
1372      * it may require type information for encoding; similarly
1373      * for generator-wrappers around Java objects or JSON nodes.
1374      * If implementation does not implement this method,
1375      * it needs to throw {@link UnsupportedOperationException}.
1376      * 
1377      * @throws UnsupportedOperationException If underlying data format does not
1378      *   support numbers serialized textually AND if generator is not allowed
1379      *   to just output a String instead (Schema-based formats may require actual
1380      *   number, for example)
1381      */

1382     public abstract void writeNumber(String encodedValue) throws IOException;
1383
1384     /**
1385      * Overloaded version of {@link #writeNumber(String)} with same semantics
1386      * but possibly more efficient operation.
1387      *
1388      * @since 2.11
1389      */

1390     public void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException {
1391         writeNumber(new String(encodedValueBuffer, offset, length));
1392     }
1393
1394     /*
1395     /**********************************************************
1396     /* Public API, write methods, other value types
1397     /**********************************************************
1398      */

1399     
1400     /**
1401      * Method for outputting literal JSON boolean value (one of
1402      * Strings 'true' and 'false').
1403      * Can be called in any context where a value is expected
1404      * (Array value, Object field value, root-level value).
1405      * Additional white space may be added around the value
1406      * if pretty-printing is enabled.
1407      */

1408     public abstract void writeBoolean(boolean state) throws IOException;
1409
1410     /**
1411      * Method for outputting literal JSON null value.
1412      * Can be called in any context where a value is expected
1413      * (Array value, Object field value, root-level value).
1414      * Additional white space may be added around the value
1415      * if pretty-printing is enabled.
1416      */

1417     public abstract void writeNull() throws IOException;
1418
1419     /**
1420      * Method that can be called on backends that support passing opaque datatypes of
1421      * non-JSON formats
1422      *
1423      * @since 2.8
1424      */

1425     public void writeEmbeddedObject(Object object) throws IOException {
1426         // 01-Sep-2016, tatu: As per [core#318], handle small number of cases
1427         if (object == null) {
1428             writeNull();
1429             return;
1430         }
1431         if (object instanceof byte[]) {
1432             writeBinary((byte[]) object);
1433             return;
1434         }
1435         throw new JsonGenerationException("No native support for writing embedded objects of type "
1436                 +object.getClass().getName(),
1437                 this);
1438     }
1439     
1440     /*
1441     /**********************************************************
1442     /* Public API, write methods, Native Ids (type, object)
1443     /**********************************************************
1444      */

1445
1446     /**
1447      * Method that can be called to output so-called native Object Id.
1448      * Note that it may only be called after ensuring this is legal
1449      * (with {@link #canWriteObjectId()}), as not all data formats
1450      * have native type id support; and some may only allow them in
1451      * certain positions or locations.
1452      * If output is not allowed by the data format in this position,
1453      * a {@link JsonGenerationException} will be thrown.
1454      * 
1455      * @since 2.3
1456      */

1457     public void writeObjectId(Object id) throws IOException {
1458         throw new JsonGenerationException("No native support for writing Object Ids"this);
1459     }
1460
1461     /**
1462      * Method that can be called to output references to native Object Ids.
1463      * Note that it may only be called after ensuring this is legal
1464      * (with {@link #canWriteObjectId()}), as not all data formats
1465      * have native type id support; and some may only allow them in
1466      * certain positions or locations.
1467      * If output is not allowed by the data format in this position,
1468      * a {@link JsonGenerationException} will be thrown.
1469      */

1470     public void writeObjectRef(Object id) throws IOException {
1471         throw new JsonGenerationException("No native support for writing Object Ids"this);
1472     }
1473     
1474     /**
1475      * Method that can be called to output so-called native Type Id.
1476      * Note that it may only be called after ensuring this is legal
1477      * (with {@link #canWriteTypeId()}), as not all data formats
1478      * have native type id support; and some may only allow them in
1479      * certain positions or locations.
1480      * If output is not allowed by the data format in this position,
1481      * a {@link JsonGenerationException} will be thrown.
1482      * 
1483      * @since 2.3
1484      */

1485     public void writeTypeId(Object id) throws IOException {
1486         throw new JsonGenerationException("No native support for writing Type Ids"this);
1487     }
1488
1489     /*
1490      * Replacement method for {@link #writeTypeId(Object)} which is called
1491      * regardless of whether format has native type ids. If it does have native
1492      * type ids, those are to be used (if configuration allows this), if not,
1493      * structural type id inclusion is to be used. For JSON, for example, no
1494      * native type ids exist and structural inclusion is always used.
1495      *<p>
1496      * NOTE: databind may choose to skip calling this method for some special cases
1497      * (and instead included type id via regular write methods and/or {@link #writeTypeId}
1498      * -- this is discouraged, but not illegal, and may be necessary as a work-around
1499      * in some cases.
1500      *
1501      * @since 2.9
1502      */

1503     public WritableTypeId writeTypePrefix(WritableTypeId typeIdDef) throws IOException
1504     {
1505         Object id = typeIdDef.id;
1506
1507         final JsonToken valueShape = typeIdDef.valueShape;
1508         if (canWriteTypeId()) {
1509             typeIdDef.wrapperWritten = false;
1510             // just rely on native type output method (sub-classes likely to override)
1511             writeTypeId(id);
1512         } else {
1513             // No native type id; write wrappers
1514             // Normally we only support String type ids (non-String reserved for native type ids)
1515             String idStr = (id instanceof String) ? (String) id : String.valueOf(id);
1516             typeIdDef.wrapperWritten = true;
1517
1518             Inclusion incl = typeIdDef.include;
1519             // first: can not output "as property" if value not Object; if so, must do "as array"
1520             if ((valueShape != JsonToken.START_OBJECT)
1521                     && incl.requiresObjectContext()) {
1522                 typeIdDef.include = incl = WritableTypeId.Inclusion.WRAPPER_ARRAY;
1523             }
1524             
1525             switch (incl) {
1526             case PARENT_PROPERTY:
1527                 // nothing to do here, as it has to be written in suffix...
1528                 break;
1529             case PAYLOAD_PROPERTY:
1530                 // only output as native type id; otherwise caller must handle using some
1531                 // other mechanism, so...
1532                 break;
1533             case METADATA_PROPERTY:
1534                 // must have Object context by now, so simply write as field name
1535                 // Note, too, that it's bit tricky, since we must print START_OBJECT that is part
1536                 // of value first -- and then NOT output it later on: hence return "early"
1537                 writeStartObject(typeIdDef.forValue);
1538                 writeStringField(typeIdDef.asProperty, idStr);
1539                 return typeIdDef;
1540
1541             case WRAPPER_OBJECT:
1542                 // NOTE: this is wrapper, not directly related to value to output, so don't pass
1543                 writeStartObject();
1544                 writeFieldName(idStr);
1545                 break;
1546             case WRAPPER_ARRAY:
1547             default// should never occur but translate as "as-array"
1548                 writeStartArray(); // wrapper, not actual array object to write
1549                 writeString(idStr);
1550             }
1551         }
1552         // and finally possible start marker for value itself:
1553         if (valueShape == JsonToken.START_OBJECT) {
1554             writeStartObject(typeIdDef.forValue);
1555         } else if (valueShape == JsonToken.START_ARRAY) {
1556             // should we now set the current object?
1557             writeStartArray();
1558         }
1559         return typeIdDef;
1560     }
1561
1562     /*
1563      * @since 2.9
1564      */

1565     public WritableTypeId writeTypeSuffix(WritableTypeId typeIdDef) throws IOException
1566     {
1567         final JsonToken valueShape = typeIdDef.valueShape;
1568         // First: does value need closing?
1569         if (valueShape == JsonToken.START_OBJECT) {
1570             writeEndObject();
1571         } else if (valueShape == JsonToken.START_ARRAY) {
1572             writeEndArray();
1573         }
1574
1575         if (typeIdDef.wrapperWritten) {
1576             switch (typeIdDef.include) {
1577             case WRAPPER_ARRAY:
1578                 writeEndArray();
1579                 break;
1580             case PARENT_PROPERTY:
1581                 // unusually, need to output AFTER value. And no real wrapper...
1582                 {
1583                     Object id = typeIdDef.id;
1584                     String idStr = (id instanceof String) ? (String) id : String.valueOf(id);
1585                     writeStringField(typeIdDef.asProperty, idStr);
1586                 }
1587                 break;
1588             case METADATA_PROPERTY:
1589             case PAYLOAD_PROPERTY:
1590                 // no actual wrapper; included within Object itself
1591                 break;
1592             case WRAPPER_OBJECT:
1593             default// should never occur but...
1594                 writeEndObject();
1595                 break;
1596             }
1597         }
1598         return typeIdDef;
1599     }
1600
1601     /*
1602     /**********************************************************
1603     /* Public API, write methods, serializing Java objects
1604     /**********************************************************
1605      */

1606
1607     /**
1608      * Method for writing given Java object (POJO) as Json.
1609      * Exactly how the object gets written depends on object
1610      * in question (ad on codec, its configuration); for most
1611      * beans it will result in JSON Object, but for others JSON
1612      * Array, or String or numeric value (and for nulls, JSON
1613      * null literal.
1614      * <b>NOTE</b>: generator must have its <b>object codec</b>
1615      * set to non-null value; for generators created by a mapping
1616      * factory this is the casefor others not.
1617      */

1618     public abstract void writeObject(Object pojo) throws IOException;
1619
1620     /**
1621      * Method for writing given JSON tree (expressed as a tree
1622      * where given JsonNode is the root) using this generator.
1623      * This will generally just call
1624      * {@link #writeObject} with given node, but is added
1625      * for convenience and to make code more explicit in cases
1626      * where it deals specifically with trees.
1627      */

1628     public abstract void writeTree(TreeNode rootNode) throws IOException;
1629
1630     /*
1631     /**********************************************************
1632     /* Public API, convenience field write methods
1633     /**********************************************************
1634      */

1635
1636     // 04-Oct-2019, tatu: Reminder: these could be defined final to
1637     //    remember NOT to override in delegating sub-classes -- but
1638     //    not final in 2.x to reduce compatibility issues
1639
1640     /**
1641      * Convenience method for outputting a field entry ("member")
1642      * that contains specified data in base64-encoded form.
1643      * Equivalent to:
1644      *<pre>
1645      *  writeFieldName(fieldName);
1646      *  writeBinary(value);
1647      *</pre>
1648      */

1649     public void writeBinaryField(String fieldName, byte[] data) throws IOException {
1650         writeFieldName(fieldName);
1651         writeBinary(data);
1652     }
1653
1654     /**
1655      * Convenience method for outputting a field entry ("member")
1656      * that has a boolean value. Equivalent to:
1657      *<pre>
1658      *  writeFieldName(fieldName);
1659      *  writeBoolean(value);
1660      *</pre>
1661      */

1662     public void writeBooleanField(String fieldName, boolean value) throws IOException {
1663         writeFieldName(fieldName);
1664         writeBoolean(value);
1665     }
1666
1667     /**
1668      * Convenience method for outputting a field entry ("member")
1669      * that has JSON literal value null. Equivalent to:
1670      *<pre>
1671      *  writeFieldName(fieldName);
1672      *  writeNull();
1673      *</pre>
1674      */

1675     public void writeNullField(String fieldName) throws IOException {
1676         writeFieldName(fieldName);
1677         writeNull();
1678     }
1679
1680     /**
1681      * Convenience method for outputting a field entry ("member")
1682      * that has a String value. Equivalent to:
1683      *<pre>
1684      *  writeFieldName(fieldName);
1685      *  writeString(value);
1686      *</pre>
1687      *<p>
1688      * Note: many performance-sensitive implementations override this method
1689      */

1690     public void writeStringField(String fieldName, String value) throws IOException {
1691         writeFieldName(fieldName);
1692         writeString(value);
1693     }
1694
1695     /**
1696      * Convenience method for outputting a field entry ("member")
1697      * that has the specified numeric value. Equivalent to:
1698      *<pre>
1699      *  writeFieldName(fieldName);
1700      *  writeNumber(value);
1701      *</pre>
1702      *
1703      * @since 2.11
1704      */

1705     public void writeNumberField(String fieldName, short value) throws IOException {
1706         writeFieldName(fieldName);
1707         writeNumber(value);
1708     }
1709
1710     /**
1711      * Convenience method for outputting a field entry ("member")
1712      * that has the specified numeric value. Equivalent to:
1713      *<pre>
1714      *  writeFieldName(fieldName);
1715      *  writeNumber(value);
1716      *</pre>
1717      */

1718     public void writeNumberField(String fieldName, int value) throws IOException {
1719         writeFieldName(fieldName);
1720         writeNumber(value);
1721     }
1722
1723     /**
1724      * Convenience method for outputting a field entry ("member")
1725      * that has the specified numeric value. Equivalent to:
1726      *<pre>
1727      *  writeFieldName(fieldName);
1728      *  writeNumber(value);
1729      *</pre>
1730      */

1731     public void writeNumberField(String fieldName, long value) throws IOException {
1732         writeFieldName(fieldName);
1733         writeNumber(value);
1734     }
1735
1736     /**
1737      * Convenience method for outputting a field entry ("member")
1738      * that has the specified numeric value. Equivalent to:
1739      *<pre>
1740      *  writeFieldName(fieldName);
1741      *  writeNumber(value);
1742      *</pre>
1743      *
1744      * @since 2.11
1745      */

1746     public void writeNumberField(String fieldName, BigInteger value) throws IOException {
1747         writeFieldName(fieldName);
1748         writeNumber(value);
1749     }
1750
1751     /**
1752      * Convenience method for outputting a field entry ("member")
1753      * that has the specified numeric value. Equivalent to:
1754      *<pre>
1755      *  writeFieldName(fieldName);
1756      *  writeNumber(value);
1757      *</pre>
1758      */

1759     public void writeNumberField(String fieldName, float value) throws IOException {
1760         writeFieldName(fieldName);
1761         writeNumber(value);
1762     }
1763
1764     /**
1765      * Convenience method for outputting a field entry ("member")
1766      * that has the specified numeric value. Equivalent to:
1767      *<pre>
1768      *  writeFieldName(fieldName);
1769      *  writeNumber(value);
1770      *</pre>
1771      */

1772     public void writeNumberField(String fieldName, double value) throws IOException {
1773         writeFieldName(fieldName);
1774         writeNumber(value);
1775     }
1776
1777     /**
1778      * Convenience method for outputting a field entry ("member")
1779      * that has the specified numeric value.
1780      * Equivalent to:
1781      *<pre>
1782      *  writeFieldName(fieldName);
1783      *  writeNumber(value);
1784      *</pre>
1785      */

1786     public void writeNumberField(String fieldName, BigDecimal value) throws IOException {
1787         writeFieldName(fieldName);
1788         writeNumber(value);
1789     }
1790
1791     /**
1792      * Convenience method for outputting a field entry ("member")
1793      * (that will contain a JSON Array value), and the START_ARRAY marker.
1794      * Equivalent to:
1795      *<pre>
1796      *  writeFieldName(fieldName);
1797      *  writeStartArray();
1798      *</pre>
1799      *<p>
1800      * Note: caller still has to take care to close the array
1801      * (by calling {#link #writeEndArray}) after writing all values
1802      * of the value Array.
1803      */

1804     public void writeArrayFieldStart(String fieldName) throws IOException {
1805         writeFieldName(fieldName);
1806         writeStartArray();
1807     }
1808
1809     /**
1810      * Convenience method for outputting a field entry ("member")
1811      * (that will contain an Object value), and the START_OBJECT marker.
1812      * Equivalent to:
1813      *<pre>
1814      *  writeFieldName(fieldName);
1815      *  writeStartObject();
1816      *</pre>
1817      *<p>
1818      * Note: caller still has to take care to close the Object
1819      * (by calling {#link #writeEndObject}) after writing all
1820      * entries of the value Object.
1821      */

1822     public void writeObjectFieldStart(String fieldName) throws IOException {
1823         writeFieldName(fieldName);
1824         writeStartObject();
1825     }
1826
1827     /**
1828      * Convenience method for outputting a field entry ("member")
1829      * that has contents of specific Java object as its value.
1830      * Equivalent to:
1831      *<pre>
1832      *  writeFieldName(fieldName);
1833      *  writeObject(pojo);
1834      *</pre>
1835      */

1836     public void writeObjectField(String fieldName, Object pojo) throws IOException {
1837         writeFieldName(fieldName);
1838         writeObject(pojo);
1839     }
1840
1841     // // // But this method does need to be delegate so...
1842     
1843     /**
1844      * Method called to indicate that a property in this position was
1845      * skipped. It is usually only called for generators that return
1846      * <code>false</code> from {@link #canOmitFields()}.
1847      *<p>
1848      * Default implementation does nothing.
1849      * 
1850      * @since 2.3
1851      */

1852     public void writeOmittedField(String fieldName) throws IOException { }
1853     
1854     /*
1855     /**********************************************************
1856     /* Public API, copy-through methods
1857     /**********************************************************
1858      */

1859
1860     /**
1861      * Method for copying contents of the current event that
1862      * the given parser instance points to.
1863      * Note that the method <b>will not</b> copy any other events,
1864      * such as events contained within JSON Array or Object structures.
1865      *<p>
1866      * Calling this method will not advance the given
1867      * parser, although it may cause parser to internally process
1868      * more data (if it lazy loads contents of value events, for example)
1869      */

1870     public void copyCurrentEvent(JsonParser p) throws IOException
1871     {
1872         JsonToken t = p.currentToken();
1873         final int token = (t == null) ? ID_NOT_AVAILABLE : t.id();
1874         switch (token) {
1875         case ID_NOT_AVAILABLE:
1876             _reportError("No current event to copy");
1877             break// never gets here
1878         case ID_START_OBJECT:
1879             writeStartObject();
1880             break;
1881         case ID_END_OBJECT:
1882             writeEndObject();
1883             break;
1884         case ID_START_ARRAY:
1885             writeStartArray();
1886             break;
1887         case ID_END_ARRAY:
1888             writeEndArray();
1889             break;
1890         case ID_FIELD_NAME:
1891             writeFieldName(p.getCurrentName());
1892             break;
1893         case ID_STRING:
1894             if (p.hasTextCharacters()) {
1895                 writeString(p.getTextCharacters(), p.getTextOffset(), p.getTextLength());
1896             } else {
1897                 writeString(p.getText());
1898             }
1899             break;
1900         case ID_NUMBER_INT:
1901         {
1902             NumberType n = p.getNumberType();
1903             if (n == NumberType.INT) {
1904                 writeNumber(p.getIntValue());
1905             } else if (n == NumberType.BIG_INTEGER) {
1906                 writeNumber(p.getBigIntegerValue());
1907             } else {
1908                 writeNumber(p.getLongValue());
1909             }
1910             break;
1911         }
1912         case ID_NUMBER_FLOAT:
1913         {
1914             NumberType n = p.getNumberType();
1915             if (n == NumberType.BIG_DECIMAL) {
1916                 writeNumber(p.getDecimalValue());
1917             } else if (n == NumberType.FLOAT) {
1918                 writeNumber(p.getFloatValue());
1919             } else {
1920                 writeNumber(p.getDoubleValue());
1921             }
1922             break;
1923         }
1924         case ID_TRUE:
1925             writeBoolean(true);
1926             break;
1927         case ID_FALSE:
1928             writeBoolean(false);
1929             break;
1930         case ID_NULL:
1931             writeNull();
1932             break;
1933         case ID_EMBEDDED_OBJECT:
1934             writeObject(p.getEmbeddedObject());
1935             break;
1936         default:
1937             throw new IllegalStateException("Internal error: unknown current token, "+t);
1938         }
1939     }
1940
1941     /**
1942      * Method for copying contents of the current event
1943      * <b>and following events that it encloses</b>
1944      * the given parser instance points to.
1945      *<p>
1946      * So what constitutes enclosing? Here is the list of
1947      * events that have associated enclosed events that will
1948      * get copied:
1949      *<ul>
1950      * <li>{@link JsonToken#START_OBJECT}:
1951      *   all events up to and including matching (closing)
1952      *   {@link JsonToken#END_OBJECT} will be copied
1953      *  </li>
1954      * <li>{@link JsonToken#START_ARRAY}
1955      *   all events up to and including matching (closing)
1956      *   {@link JsonToken#END_ARRAY} will be copied
1957      *  </li>
1958      * <li>{@link JsonToken#FIELD_NAME} the logical value (which
1959      *   can consist of a single scalar value; or a sequence of related
1960      *   events for structured types (JSON Arrays, Objects)) will
1961      *   be copied along with the name itself. So essentially the
1962      *   whole <b>field entry</b> (name and value) will be copied.
1963      *  </li>
1964      *</ul>
1965      *<p>
1966      * After calling this method, parser will point to the
1967      * <b>last event</b> that was copied. This will either be
1968      * the event parser already pointed to (if there were no
1969      * enclosed events), or the last enclosed event copied.
1970      */

1971     public void copyCurrentStructure(JsonParser p) throws IOException
1972     {
1973         JsonToken t = p.currentToken();
1974         // Let's handle field-name separately first
1975         int id = (t == null) ? ID_NOT_AVAILABLE : t.id();
1976         if (id == ID_FIELD_NAME) {
1977             writeFieldName(p.getCurrentName());
1978             t = p.nextToken();
1979             id = (t == null) ? ID_NOT_AVAILABLE : t.id();
1980             // fall-through to copy the associated value
1981         }
1982         switch (id) {
1983         case ID_START_OBJECT:
1984             writeStartObject();
1985             _copyCurrentContents(p);
1986             return;
1987         case ID_START_ARRAY:
1988             writeStartArray();
1989             _copyCurrentContents(p);
1990             return;
1991
1992         default:
1993             copyCurrentEvent(p);
1994         }
1995     }
1996
1997     /**
1998      * @since 2.10
1999      */

2000     protected void _copyCurrentContents(JsonParser p) throws IOException
2001     {
2002         int depth = 1;
2003         JsonToken t;
2004
2005         // Mostly copied from `copyCurrentEvent()`, but with added nesting counts
2006         while ((t = p.nextToken()) != null) {
2007             switch (t.id()) {
2008             case ID_FIELD_NAME:
2009                 writeFieldName(p.getCurrentName());
2010                 break;
2011
2012             case ID_START_ARRAY:
2013                 writeStartArray();
2014                 ++depth;
2015                 break;
2016
2017             case ID_START_OBJECT:
2018                 writeStartObject();
2019                 ++depth;
2020                 break;
2021
2022             case ID_END_ARRAY:
2023                 writeEndArray();
2024                 if (--depth == 0) {
2025                     return;
2026                 }
2027                 break;
2028             case ID_END_OBJECT:
2029                 writeEndObject();
2030                 if (--depth == 0) {
2031                     return;
2032                 }
2033                 break;
2034
2035             case ID_STRING:
2036                 if (p.hasTextCharacters()) {
2037                     writeString(p.getTextCharacters(), p.getTextOffset(), p.getTextLength());
2038                 } else {
2039                     writeString(p.getText());
2040                 }
2041                 break;
2042             case ID_NUMBER_INT:
2043             {
2044                 NumberType n = p.getNumberType();
2045                 if (n == NumberType.INT) {
2046                     writeNumber(p.getIntValue());
2047                 } else if (n == NumberType.BIG_INTEGER) {
2048                     writeNumber(p.getBigIntegerValue());
2049                 } else {
2050                     writeNumber(p.getLongValue());
2051                 }
2052                 break;
2053             }
2054             case ID_NUMBER_FLOAT:
2055             {
2056                 NumberType n = p.getNumberType();
2057                 if (n == NumberType.BIG_DECIMAL) {
2058                     writeNumber(p.getDecimalValue());
2059                 } else if (n == NumberType.FLOAT) {
2060                     writeNumber(p.getFloatValue());
2061                 } else {
2062                     writeNumber(p.getDoubleValue());
2063                 }
2064                 break;
2065             }
2066             case ID_TRUE:
2067                 writeBoolean(true);
2068                 break;
2069             case ID_FALSE:
2070                 writeBoolean(false);
2071                 break;
2072             case ID_NULL:
2073                 writeNull();
2074                 break;
2075             case ID_EMBEDDED_OBJECT:
2076                 writeObject(p.getEmbeddedObject());
2077                 break;
2078             default:
2079                 throw new IllegalStateException("Internal error: unknown current token, "+t);
2080             }
2081         }
2082     }
2083
2084     /*
2085     /**********************************************************
2086     /* Public API, context access
2087     /**********************************************************
2088      */

2089
2090     /**
2091      * @return Context object that can give information about logical
2092      *   position within generated json content.
2093      */

2094     public abstract JsonStreamContext getOutputContext();
2095
2096     /*
2097     /**********************************************************
2098     /* Public API, buffer handling
2099     /**********************************************************
2100      */

2101
2102     /**
2103      * Method called to flush any buffered content to the underlying
2104      * target (output stream, writer), and to flush the target itself
2105      * as well.
2106      */

2107     @Override
2108     public abstract void flush() throws IOException;
2109
2110     /**
2111      * Method that can be called to determine whether this generator
2112      * is closed or not. If it is closed, no more output can be done.
2113      */

2114     public abstract boolean isClosed();
2115
2116     /*
2117     /**********************************************************
2118     /* Closeable implementation
2119     /**********************************************************
2120      */

2121
2122     /**
2123      * Method called to close this generator, so that no more content
2124      * can be written.
2125      *<p>
2126      * Whether the underlying target (stream, writer) gets closed depends
2127      * on whether this generator either manages the target (i.e. is the
2128      * only one with access to the target -- case if caller passes a
2129      * reference to the resource such as File, but not stream); or
2130      * has feature {@link Feature#AUTO_CLOSE_TARGET} enabled.
2131      * If either of above is true, the target is also closed. Otherwise
2132      * (not managing, feature not enabled), target is not closed.
2133      */

2134     @Override
2135     public abstract void close() throws IOException;
2136
2137     /*
2138     /**********************************************************
2139     /* Helper methods for sub-classes
2140     /**********************************************************
2141      */

2142
2143     /**
2144      * Helper method used for constructing and throwing
2145      * {@link JsonGenerationException} with given base message.
2146      *<p>
2147      * Note that sub-classes may override this method to add more detail
2148      * or use a {@link JsonGenerationException} sub-class.
2149      */

2150     protected void _reportError(String msg) throws JsonGenerationException {
2151         throw new JsonGenerationException(msg, this);
2152     }
2153
2154     protected final void _throwInternal() { VersionUtil.throwInternal(); }
2155
2156     protected void _reportUnsupportedOperation() {
2157         throw new UnsupportedOperationException("Operation not supported by generator of type "+getClass().getName());
2158     }
2159
2160     /**
2161      * @since 2.8
2162      */

2163     protected final void _verifyOffsets(int arrayLength, int offset, int length)
2164     {
2165         if ((offset < 0) || (offset + length) > arrayLength) {
2166             throw new IllegalArgumentException(String.format(
2167                     "invalid argument(s) (offset=%d, length=%d) for input array of %d element",
2168                     offset, length, arrayLength));
2169         }
2170     }
2171
2172     /**
2173      * Helper method to try to call appropriate write method for given
2174      * untyped Object. At this point, no structural conversions should be done,
2175      * only simple basic types are to be coerced as necessary.
2176      *
2177      * @param value Non-null value to write
2178      */

2179     protected void _writeSimpleObject(Object value)  throws IOException
2180     {
2181         // 31-Dec-2009, tatu: Actually, we could just handle some basic
2182         //    types even without codec. This can improve interoperability,
2183         //    and specifically help with TokenBuffer.
2184         if (value == null) {
2185             writeNull();
2186             return;
2187         }
2188         if (value instanceof String) {
2189             writeString((String) value);
2190             return;
2191         }
2192         if (value instanceof Number) {
2193             Number n = (Number) value;
2194             if (n instanceof Integer) {
2195                 writeNumber(n.intValue());
2196                 return;
2197             } else if (n instanceof Long) {
2198                 writeNumber(n.longValue());
2199                 return;
2200             } else if (n instanceof Double) {
2201                 writeNumber(n.doubleValue());
2202                 return;
2203             } else if (n instanceof Float) {
2204                 writeNumber(n.floatValue());
2205                 return;
2206             } else if (n instanceof Short) {
2207                 writeNumber(n.shortValue());
2208                 return;
2209             } else if (n instanceof Byte) {
2210                 writeNumber(n.byteValue());
2211                 return;
2212             } else if (n instanceof BigInteger) {
2213                 writeNumber((BigInteger) n);
2214                 return;
2215             } else if (n instanceof BigDecimal) {
2216                 writeNumber((BigDecimal) n);
2217                 return;
2218
2219             // then Atomic types
2220             } else if (n instanceof AtomicInteger) {
2221                 writeNumber(((AtomicInteger) n).get());
2222                 return;
2223             } else if (n instanceof AtomicLong) {
2224                 writeNumber(((AtomicLong) n).get());
2225                 return;
2226             }
2227         } else if (value instanceof byte[]) {
2228             writeBinary((byte[]) value);
2229             return;
2230         } else if (value instanceof Boolean) {
2231             writeBoolean((Boolean) value);
2232             return;
2233         } else if (value instanceof AtomicBoolean) {
2234             writeBoolean(((AtomicBoolean) value).get());
2235             return;
2236         }
2237         throw new IllegalStateException("No ObjectCodec defined for the generator, can only serialize simple wrapper types (type passed "
2238                 +value.getClass().getName()+")");
2239     }    
2240 }
2241