Skip to content

Commit b7c38a1

Browse files
committed
[CSV-233] Add predefined CSVFormats for printing MongoDB CSV and TSV.
1 parent c7a9b17 commit b7c38a1

5 files changed

Lines changed: 364 additions & 182 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
<action issue="CSV-209" type="fix" dev="ggregory" due-to="Gary Gregory">Create CSVFormat.ORACLE preset.</action>
5151
<action issue="CSV-224" type="fix" dev="ggregory" due-to="David Warshaw">Some multi-iterator parsing peek sequences incorrectly consume elements.</action>
5252
<action issue="CSV-225" type="fix" dev="ggregory" due-to="Anson Schwabecher">Parse method should avoid creating a redundant BufferedReader.</action>
53+
<action issue="CSV-233" type="fix" dev="ggregory" due-to="Gary Gregory">Add predefined CSVFormats for printing MongoDB CSV and TSV.</action>
5354
</release>
5455
<release version="1.5" date="2017-09-03" description="Feature and bug fix release">
5556
<action issue="CSV-203" type="fix" dev="ggregory" due-to="Richard Wheeldon, Kai Paroth">withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17.</action>

src/main/java/org/apache/commons/csv/CSVFormat.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ public enum Predefined {
189189
*/
190190
InformixUnloadCsv(CSVFormat.INFORMIX_UNLOAD_CSV),
191191

192+
/**
193+
* @see CSVFormat#MONGODB_CSV
194+
* @since 1.7
195+
*/
196+
MongoDBCsv(CSVFormat.MONGODB_CSV),
197+
198+
/**
199+
* @see CSVFormat#MONGODB_TSV
200+
* @since 1.7
201+
*/
202+
MongoDBTsv(CSVFormat.MONGODB_TSV),
203+
192204
/**
193205
* @see CSVFormat#MYSQL
194206
*/
@@ -351,6 +363,78 @@ public CSVFormat getFormat() {
351363
.withRecordSeparator(LF);
352364
// @formatter:on
353365

366+
/**
367+
* Default MongoDB CSV format used by the {@code mongoexport} operation.
368+
* <p>
369+
* <b>Parsing is not supported yet.</b>
370+
* </p>
371+
*
372+
* <p>
373+
* This is a comma-delimited format. Values are double quoted only if needed and special characters are escaped with
374+
* {@code '"'}. A header line with field names is expected.
375+
* </p>
376+
*
377+
* <p>
378+
* Settings are:
379+
* </p>
380+
* <ul>
381+
* <li>{@code withDelimiter(',')}</li>
382+
* <li>{@code withEscape('"')}</li>
383+
* <li>{@code withQuote('"')}</li>
384+
* <li>{@code withQuoteMode(QuoteMode.ALL_NON_NULL)}</li>
385+
* <li>{@code withSkipHeaderRecord(false)}</li>
386+
* </ul>
387+
*
388+
* @see Predefined#MongoDBCsv
389+
* @see <a href="https://docs.mongodb.com/manual/reference/program/mongoexport/">MongoDB mongoexport command
390+
* documentation</a>
391+
* @since 1.7
392+
*/
393+
// @formatter:off
394+
public static final CSVFormat MONGODB_CSV = DEFAULT
395+
.withDelimiter(COMMA)
396+
.withEscape(DOUBLE_QUOTE_CHAR)
397+
.withQuote(DOUBLE_QUOTE_CHAR)
398+
.withQuoteMode(QuoteMode.MINIMAL)
399+
.withSkipHeaderRecord(false);
400+
// @formatter:off
401+
402+
/**
403+
* Default MongoDB TSV format used by the {@code mongoexport} operation.
404+
* <p>
405+
* <b>Parsing is not supported yet.</b>
406+
* </p>
407+
*
408+
* <p>
409+
* This is a tab-delimited format. Values are double quoted only if needed and special
410+
* characters are escaped with {@code '"'}. A header line with field names is expected.
411+
* </p>
412+
*
413+
* <p>
414+
* Settings are:
415+
* </p>
416+
* <ul>
417+
* <li>{@code withDelimiter('\t')}</li>
418+
* <li>{@code withEscape('"')}</li>
419+
* <li>{@code withQuote('"')}</li>
420+
* <li>{@code withQuoteMode(QuoteMode.ALL_NON_NULL)}</li>
421+
* <li>{@code withSkipHeaderRecord(false)}</li>
422+
* </ul>
423+
*
424+
* @see Predefined#MongoDBCsv
425+
* @see <a href="https://docs.mongodb.com/manual/reference/program/mongoexport/">MongoDB mongoexport command
426+
* documentation</a>
427+
* @since 1.7
428+
*/
429+
// @formatter:off
430+
public static final CSVFormat MONGODB_TSV = DEFAULT
431+
.withDelimiter(TAB)
432+
.withEscape(DOUBLE_QUOTE_CHAR)
433+
.withQuote(DOUBLE_QUOTE_CHAR)
434+
.withQuoteMode(QuoteMode.MINIMAL)
435+
.withSkipHeaderRecord(false);
436+
// @formatter:off
437+
354438
/**
355439
* Default MySQL format used by the {@code SELECT INTO OUTFILE} and {@code LOAD DATA INFILE} operations.
356440
*

src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ public void testPostgreSqlCsv() {
5555
test(CSVFormat.POSTGRESQL_CSV, "PostgreSQLCsv");
5656
}
5757

58+
@Test
59+
public void testMongoDbCsv() {
60+
test(CSVFormat.MONGODB_CSV, "MongoDBCsv");
61+
}
62+
63+
@Test
64+
public void testMongoDbTsv() {
65+
test(CSVFormat.MONGODB_TSV, "MongoDBTsv");
66+
}
67+
5868
@Test
5969
public void testPostgreSqlText() {
6070
test(CSVFormat.POSTGRESQL_TEXT, "PostgreSQLText");

src/test/java/org/apache/commons/csv/CSVParserTest.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -773,19 +773,37 @@ record = records.next();
773773
assertFalse(records.hasNext());
774774
}
775775

776+
@Test
777+
@Ignore
778+
public void testMongoDbCsv() throws Exception {
779+
try (final CSVParser parser = CSVParser.parse("\"a a\",b,c" + LF + "d,e,f", CSVFormat.MONGODB_CSV)) {
780+
final Iterator<CSVRecord> itr1 = parser.iterator();
781+
final Iterator<CSVRecord> itr2 = parser.iterator();
782+
783+
final CSVRecord first = itr1.next();
784+
assertEquals("a a", first.get(0));
785+
assertEquals("b", first.get(1));
786+
assertEquals("c", first.get(2));
787+
788+
final CSVRecord second = itr2.next();
789+
assertEquals("d", second.get(0));
790+
assertEquals("e", second.get(1));
791+
assertEquals("f", second.get(2));
792+
}
793+
}
794+
776795
@Test
777796
// TODO this may lead to strange behavior, throw an exception if iterator() has already been called?
778797
public void testMultipleIterators() throws Exception {
779-
try (final CSVParser parser = CSVParser.parse("a,b,c" + CR + "d,e,f", CSVFormat.DEFAULT)) {
798+
try (final CSVParser parser = CSVParser.parse("a,b,c" + CRLF + "d,e,f", CSVFormat.DEFAULT)) {
780799
final Iterator<CSVRecord> itr1 = parser.iterator();
781-
final Iterator<CSVRecord> itr2 = parser.iterator();
782800

783801
final CSVRecord first = itr1.next();
784802
assertEquals("a", first.get(0));
785803
assertEquals("b", first.get(1));
786804
assertEquals("c", first.get(2));
787805

788-
final CSVRecord second = itr2.next();
806+
final CSVRecord second = itr1.next();
789807
assertEquals("d", second.get(0));
790808
assertEquals("e", second.get(1));
791809
assertEquals("f", second.get(2));

0 commit comments

Comments
 (0)