1111import com .fasterxml .jackson .core .json .JsonWriteContext ;
1212import com .fasterxml .jackson .core .io .IOContext ;
1313import com .fasterxml .jackson .dataformat .csv .impl .CsvEncoder ;
14+ import com .fasterxml .jackson .dataformat .csv .impl .SimpleTokenWriteContext ;
1415
1516public class CsvGenerator extends GeneratorBase
1617{
@@ -159,6 +160,14 @@ private Feature(boolean defaultState) {
159160 // note: can not be final since we may need to re-create it for new schema
160161 protected CsvEncoder _writer ;
161162
163+ /**
164+ * Current context, in form we can use it (GeneratorBase has
165+ * untyped reference; left as null)
166+ *
167+ * @since 2.11
168+ */
169+ protected SimpleTokenWriteContext _csvWriteContext ;
170+
162171 protected CharacterEscapes _characterEscapes = null ;
163172
164173 /*
@@ -216,7 +225,7 @@ private Feature(boolean defaultState) {
216225 *
217226 * @since 2.7
218227 */
219- protected JsonWriteContext _skipWithin ;
228+ protected SimpleTokenWriteContext _skipWithin ;
220229
221230 /*
222231 /**********************************************************
@@ -235,7 +244,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
235244 _formatFeatures = csvFeatures ;
236245 _schema = schema ;
237246 _writer = new CsvEncoder (ctxt , csvFeatures , out , schema );
238-
247+ _csvWriteContext = SimpleTokenWriteContext . createRootContext ( null );
239248 _writer .setOutputEscapes (CsvCharacterEscapes .fromCsvFeatures (csvFeatures ).getEscapeCodesForAscii ());
240249 }
241250
@@ -246,6 +255,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
246255 _ioContext = ctxt ;
247256 _formatFeatures = csvFeatures ;
248257 _writer = csvWriter ;
258+ _csvWriteContext = SimpleTokenWriteContext .createRootContext (null );
249259 }
250260
251261 /*
@@ -298,6 +308,11 @@ public int getOutputBuffered() {
298308 return _writer .getOutputBuffered ();
299309 }
300310
311+ @ Override
312+ public SimpleTokenWriteContext getOutputContext () {
313+ return _csvWriteContext ;
314+ }
315+
301316 @ Override
302317 public void setSchema (FormatSchema schema )
303318 {
@@ -380,7 +395,7 @@ public boolean canOmitFields() {
380395 @ Override
381396 public final void writeFieldName (String name ) throws IOException
382397 {
383- if (_writeContext .writeFieldName (name ) == JsonWriteContext . STATUS_EXPECT_VALUE ) {
398+ if (! _csvWriteContext .writeFieldName (name )) {
384399 _reportError ("Can not write a field name, expecting a value" );
385400 }
386401 _writeFieldName (name );
@@ -390,7 +405,7 @@ public final void writeFieldName(String name) throws IOException
390405 public final void writeFieldName (SerializableString name ) throws IOException
391406 {
392407 // Object is a value, need to verify it's allowed
393- if (_writeContext .writeFieldName (name .getValue ()) == JsonWriteContext . STATUS_EXPECT_VALUE ) {
408+ if (! _csvWriteContext .writeFieldName (name .getValue ())) {
394409 _reportError ("Can not write a field name, expecting a value" );
395410 }
396411 _writeFieldName (name .getValue ());
@@ -492,10 +507,10 @@ public final void writeStartArray() throws IOException
492507 _verifyValueWrite ("start an array" );
493508 // Ok to create root-level array to contain Objects/Arrays, but
494509 // can not nest arrays in objects
495- if (_writeContext .inObject ()) {
510+ if (_csvWriteContext .inObject ()) {
496511 if ((_skipWithin == null )
497512 && _skipValue && isEnabled (JsonGenerator .Feature .IGNORE_UNKNOWN )) {
498- _skipWithin = _writeContext ;
513+ _skipWithin = _csvWriteContext ;
499514 } else if (!_skipValue ) {
500515 // First: column may have its own separator
501516 String sep ;
@@ -525,20 +540,20 @@ && _skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
525540 _reportError ("CSV generator does not support nested Array values" );
526541 }
527542 }
528- _writeContext = _writeContext .createChildArrayContext ();
543+ _csvWriteContext = _csvWriteContext .createChildArrayContext (null );
529544 // and that's about it, really
530545 }
531546
532547 @ Override
533548 public final void writeEndArray () throws IOException
534549 {
535- if (!_writeContext .inArray ()) {
536- _reportError ("Current context not Array but " +_writeContext .typeDesc ());
550+ if (!_csvWriteContext .inArray ()) {
551+ _reportError ("Current context not Array but " +_csvWriteContext .typeDesc ());
537552 }
538- _writeContext = _writeContext .getParent ();
553+ _csvWriteContext = _csvWriteContext .getParent ();
539554 // 14-Dec-2015, tatu: To complete skipping of ignored structured value, need this:
540555 if (_skipWithin != null ) {
541- if (_writeContext == _skipWithin ) {
556+ if (_csvWriteContext == _skipWithin ) {
542557 _skipWithin = null ;
543558 }
544559 return ;
@@ -549,7 +564,7 @@ public final void writeEndArray() throws IOException
549564 }
550565 // 20-Nov-2014, tatu: When doing "untyped"/"raw" output, this means that row
551566 // is now done. But not if writing such an array field, so:
552- if (!_writeContext .inObject ()) {
567+ if (!_csvWriteContext .inObject ()) {
553568 finishRow ();
554569 }
555570 }
@@ -560,30 +575,30 @@ public final void writeStartObject() throws IOException
560575 _verifyValueWrite ("start an object" );
561576 // No nesting for objects; can write Objects inside logical root-level arrays.
562577 // 14-Dec-2015, tatu: ... except, should be fine if we are ignoring the property
563- if (_writeContext .inObject () ||
578+ if (_csvWriteContext .inObject () ||
564579 // 07-Nov-2017, tatu: But we may actually be nested indirectly; so check
565- (_writeContext .inArray () && !_writeContext .getParent ().inRoot ())) {
580+ (_csvWriteContext .inArray () && !_csvWriteContext .getParent ().inRoot ())) {
566581 if (_skipWithin == null ) { // new in 2.7
567582 if (_skipValue && isEnabled (JsonGenerator .Feature .IGNORE_UNKNOWN )) {
568- _skipWithin = _writeContext ;
583+ _skipWithin = _csvWriteContext ;
569584 } else {
570585 _reportMappingError ("CSV generator does not support Object values for properties (nested Objects)" );
571586 }
572587 }
573588 }
574- _writeContext = _writeContext .createChildObjectContext ();
589+ _csvWriteContext = _csvWriteContext .createChildObjectContext (null );
575590 }
576591
577592 @ Override
578593 public final void writeEndObject () throws IOException
579594 {
580- if (!_writeContext .inObject ()) {
581- _reportError ("Current context not Object but " +_writeContext .typeDesc ());
595+ if (!_csvWriteContext .inObject ()) {
596+ _reportError ("Current context not Object but " +_csvWriteContext .typeDesc ());
582597 }
583- _writeContext = _writeContext .getParent ();
598+ _csvWriteContext = _csvWriteContext .getParent ();
584599 // 14-Dec-2015, tatu: To complete skipping of ignored structured value, need this:
585600 if (_skipWithin != null ) {
586- if (_writeContext == _skipWithin ) {
601+ if (_csvWriteContext == _skipWithin ) {
587602 _skipWithin = null ;
588603 }
589604 return ;
@@ -760,16 +775,16 @@ public void writeNull() throws IOException
760775 if (!_skipValue ) {
761776 if (!_arraySeparator .isEmpty ()) {
762777 _addToArray (_schema .getNullValueOrEmpty ());
763- } else if (_writeContext .inObject ()) {
778+ } else if (_csvWriteContext .inObject ()) {
764779 _writer .writeNull (_columnIndex ());
765- } else if (_writeContext .inArray ()) {
780+ } else if (_csvWriteContext .inArray ()) {
766781 // [dataformat-csv#106]: Need to make sure we don't swallow nulls in arrays either
767782 // 04-Jan-2016, tatu: but check for case of array-wrapping, in which case null stands for absence
768783 // of Object. In this case, could either add an empty row, or skip -- for now, we'll
769784 // just skip; can change, if so desired, to expose "root null" as empty rows, possibly
770785 // based on either schema property, or CsvGenerator.Feature.
771786 // Note: if nulls are to be written that way, would need to call `finishRow()` right after `writeNull()`
772- if (!_writeContext .getParent ().inRoot ()) {
787+ if (!_csvWriteContext .getParent ().inRoot ()) {
773788 _writer .writeNull (_columnIndex ());
774789 }
775790
@@ -909,7 +924,7 @@ public void writeOmittedField(String fieldName) throws IOException
909924 // assumed to have been removed from schema too
910925 } else {
911926 // basically combination of "writeFieldName()" and "writeNull()"
912- if (_writeContext .writeFieldName (fieldName ) == JsonWriteContext . STATUS_EXPECT_VALUE ) {
927+ if (! _csvWriteContext .writeFieldName (fieldName )) {
913928 _reportError ("Can not skip a field, expecting a value" );
914929 }
915930 // and all we do is just note index to use for following value write
@@ -929,8 +944,7 @@ public void writeOmittedField(String fieldName) throws IOException
929944 @ Override
930945 protected final void _verifyValueWrite (String typeMsg ) throws IOException
931946 {
932- int status = _writeContext .writeValue ();
933- if (status == JsonWriteContext .STATUS_EXPECT_NAME ) {
947+ if (!_csvWriteContext .writeValue ()) {
934948 _reportError ("Can not " +typeMsg +", expecting field name" );
935949 }
936950 if (_handleFirstLine ) {
0 commit comments