Skip to content
This repository was archived by the owner on Jan 22, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,24 @@ protected void _readHeaderLine() throws IOException {
*/

if (_schema.size() > 0 && !_schema.reordersColumns()) {
//noinspection StatementWithEmptyBody
while (_reader.nextString() != null) { /* does nothing */ }
if (_schema.strictHeaders()) {
String name;
for (CsvSchema.Column column : _schema._columns) {
name = _reader.nextString();
if (name == null) {
_reportError(String.format("Missing header %s", column.getName()));
} else if (!column.getName().equals(name)) {
_reportError(String.format("Expected header %s, actual header %s", column.getName(), name));
}
}
if ((name = _reader.nextString()) != null) {
_reportError(String.format("Extra header %s", name));
}
}
else {
//noinspection StatementWithEmptyBody
while (_reader.nextString() != null) { /* does nothing */ }
}
return;
}

Expand Down
31 changes: 31 additions & 0 deletions src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public class CsvSchema
protected final static int ENCODING_FEATURE_SKIP_FIRST_DATA_ROW = 0x0002;
protected final static int ENCODING_FEATURE_ALLOW_COMMENTS = 0x0004;
protected final static int ENCODING_FEATURE_REORDER_COLUMNS = 0x0008;
protected final static int ENCODING_FEATURE_STRICT_HEADERS = 0x0016;

protected final static int DEFAULT_ENCODING_FEATURES = 0;

Expand Down Expand Up @@ -471,6 +472,22 @@ public Builder setReorderColumns(boolean b) {
return this;
}


/**
* Use in combination with setUseHeader. When use header flag is
* is set, this setting will ensure the headers are in the order
* of the schema
*
* @param b Enable / Disable this setting
* @return This Builder instance
*
* @since 2.7
*/
public Builder setStrictHeaders(boolean b) {
_feature(ENCODING_FEATURE_STRICT_HEADERS, b);
return this;
}

/**
* Method for specifying whether Schema should indicate that
* the first line that is not a header (if header handling enabled)
Expand Down Expand Up @@ -804,6 +821,19 @@ public CsvSchema withColumnReordering(boolean state) {
return _withFeature(ENCODING_FEATURE_REORDER_COLUMNS, state);
}

/**
* Returns a clone of this instance by changing or setting the
* strict headers flag
*
* @param state New value for setting
* @return A copy of itself, ensuring the setting for
* the strict headers feature.
* @since 2.7
*/
public CsvSchema withStrictColumns(boolean state) {
return _withFeature(ENCODING_FEATURE_STRICT_HEADERS, state);
}

/**
* Helper method for constructing and returning schema instance that
* is similar to this one, except that it will be using header line.
Expand Down Expand Up @@ -1001,6 +1031,7 @@ public String getSchemaType() {
public boolean reordersColumns() { return (_features & ENCODING_FEATURE_REORDER_COLUMNS) != 0; }
public boolean skipsFirstDataRow() { return (_features & ENCODING_FEATURE_SKIP_FIRST_DATA_ROW) != 0; }
public boolean allowsComments() { return (_features & ENCODING_FEATURE_ALLOW_COMMENTS) != 0; }
public boolean strictHeaders() { return (_features & ENCODING_FEATURE_STRICT_HEADERS) != 0; }

/**
* @deprecated Use {@link #usesHeader()} instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.*;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.dataformat.csv.*;
Expand Down Expand Up @@ -328,4 +329,79 @@ public void testColumnReordering() throws IOException {
assertEquals(JsonToken.END_OBJECT, parser.nextToken());
parser.close();
}

public void testColumnFailsOnOutOfOrder() throws IOException {
CsvFactory factory = new CsvFactory();
String CSV = "b,a,c\nvb,va,vc\n";

CsvSchema schema = CsvSchema.builder()
.addColumn("a")
.addColumn("b")
.addColumn("c")
.setLineSeparator('\n')
.setUseHeader(true)
.setStrictHeaders(true)
.build();

CsvParser parser = factory.createParser(CSV);
parser.setSchema(schema);

try {
parser.nextToken();
fail("Should have failed");
} catch (JsonProcessingException e) {
verifyException(e, "Expected header a, actual header b");
}
parser.close();
}

public void testColumnFailsOnTooFew() throws IOException {
CsvFactory factory = new CsvFactory();
String CSV = "a,b\nvb,va,vc\n";

CsvSchema schema = CsvSchema.builder()
.addColumn("a")
.addColumn("b")
.addColumn("c")
.setLineSeparator('\n')
.setUseHeader(true)
.setStrictHeaders(true)
.build();

CsvParser parser = factory.createParser(CSV);
parser.setSchema(schema);

try {
parser.nextToken();
fail("Should have failed");
} catch (JsonProcessingException e) {
verifyException(e, "Missing header c");
}
parser.close();
}

public void testColumnFailsOnTooMany() throws IOException {
CsvFactory factory = new CsvFactory();
String CSV = "a,b,c,d\nvb,va,vc\n";

CsvSchema schema = CsvSchema.builder()
.addColumn("a")
.addColumn("b")
.addColumn("c")
.setLineSeparator('\n')
.setUseHeader(true)
.setStrictHeaders(true)
.build();

CsvParser parser = factory.createParser(CSV);
parser.setSchema(schema);

try {
parser.nextToken();
fail("Should have failed");
} catch (JsonProcessingException e) {
verifyException(e, "Extra header d");
}
parser.close();
}
}