Skip to content
This repository was archived by the owner on Jan 22, 2019. It is now read-only.

Commit 6c74cb4

Browse files
committed
Fix minor issues wry #79
1 parent 59a3639 commit 6c74cb4

File tree

13 files changed

+121
-33
lines changed

13 files changed

+121
-33
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ abstractions.
2626

2727
<properties>
2828
<jackson.version.annotations>2.6.0-rc1</jackson.version.annotations>
29-
<jackson.version.core>2.6.0-rc1</jackson.version.core>
29+
<jackson.version.core>2.6.0-rc2-SNAPSHOT</jackson.version.core>
3030
<!-- Generate PackageVersion.java into this directory. -->
3131
<packageVersion.dir>com/fasterxml/jackson/dataformat/csv</packageVersion.dir>
3232
<packageVersion.package>${project.groupId}.csv</packageVersion.package>

src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java

+29-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.fasterxml.jackson.core.json.DupDetector;
1010
import com.fasterxml.jackson.core.json.JsonReadContext;
1111
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
12+
1213
import com.fasterxml.jackson.dataformat.csv.impl.CsvDecoder;
1314
import com.fasterxml.jackson.dataformat.csv.impl.CsvIOContext;
1415
import com.fasterxml.jackson.dataformat.csv.impl.TextBuffer;
@@ -138,14 +139,23 @@ private Feature(boolean defaultState) {
138139
*/
139140
protected final static int STATE_IN_ARRAY = 5;
140141

142+
/**
143+
* State in which we have encountered more column values than there should be,
144+
* and need to basically skip extra values if callers tries to advance parser
145+
* state.
146+
*
147+
* @since 2.6
148+
*/
149+
protected final static int STATE_SKIP_EXTRA_COLUMNS = 6;
150+
141151
/**
142152
* State in which end marker is returned; either
143153
* null (if no array wrapping), or
144154
* {@link JsonToken#END_ARRAY} for wrapping.
145155
* This step will loop, returning series of nulls
146156
* if {@link #nextToken} is called multiple times.
147157
*/
148-
protected final static int STATE_DOC_END = 6;
158+
protected final static int STATE_DOC_END = 7;
149159

150160
/*
151161
/**********************************************************************
@@ -476,6 +486,19 @@ public JsonToken nextToken() throws IOException
476486
return (_currToken = _handleUnnamedValue());
477487
case STATE_IN_ARRAY:
478488
return (_currToken = _handleArrayValue());
489+
case STATE_SKIP_EXTRA_COLUMNS:
490+
// Need to just skip whatever remains
491+
_state = STATE_RECORD_START;
492+
while (_reader.nextString() != null) { }
493+
494+
// But once we hit the end of the logical line, get out
495+
// NOTE: seems like we should always be within Object, but let's be conservative
496+
// and check just in case
497+
_parsingContext = _parsingContext.getParent();
498+
_state = _reader.startNewLine() ? STATE_RECORD_START : STATE_DOC_END;
499+
return (_currToken = _parsingContext.inArray()
500+
? JsonToken.END_ARRAY : JsonToken.END_OBJECT);
501+
479502
case STATE_DOC_END:
480503
_reader.close();
481504
if (_parsingContext.inRoot()) {
@@ -645,7 +668,9 @@ protected JsonToken _handleNextEntry() throws IOException
645668
return _handleNextEntryExpectEOL();
646669
}
647670
}
648-
_reportError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
671+
// 21-May-2015, tatu: Need to enter recovery mode, to skip remainder of the line
672+
_state = STATE_SKIP_EXTRA_COLUMNS;
673+
_reportCsvError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
649674
}
650675
_currentName = _schema.columnName(_columnIndex);
651676
return JsonToken.FIELD_NAME;
@@ -656,7 +681,7 @@ protected JsonToken _handleNextEntryExpectEOL() throws IOException
656681
String next = _reader.nextString();
657682

658683
if (next != null) { // should end of record or input
659-
_reportError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
684+
_reportCsvError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
660685
}
661686
_parsingContext = _parsingContext.getParent();
662687
if (!_reader.startNewLine()) {
@@ -923,7 +948,7 @@ public void _reportCsvError(String msg) throws JsonParseException {
923948
public void _reportUnexpectedCsvChar(int ch, String msg) throws JsonParseException {
924949
super._reportUnexpectedChar(ch, msg);
925950
}
926-
951+
927952
/*
928953
/**********************************************************************
929954
/* Internal methods

src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvDecoder.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,12 @@ protected int _skipCommentLines() throws IOException
560560
}
561561
return -1; // end of input
562562
}
563-
563+
564+
/**
565+
* Method called to blindly skip a single line of content, without considering
566+
* aspects like quoting or escaping. Used currently simply to skip the first
567+
* line of input document, if instructed to do so.
568+
*/
564569
public boolean skipLine() throws IOException
565570
{
566571
if (_pendingLF != 0) {

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/CommentsTest.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void testWithoutComments() throws Exception
2424

2525
// First, with comments disabled:
2626

27-
MappingIterator<String[]> it = mapper.reader(String[].class)
27+
MappingIterator<String[]> it = mapper.readerFor(String[].class)
2828
.with(mapper.schema().withoutComments()).readValues(CSV_WITH_COMMENTS);
2929

3030
row = it.nextValue();
@@ -61,7 +61,7 @@ public void testSimpleComments() throws Exception
6161
// should not be needed but seems to be...
6262
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
6363

64-
MappingIterator<String[]> it = mapper.reader(String[].class)
64+
MappingIterator<String[]> it = mapper.readerFor(String[].class)
6565
.with(mapper.schema().withComments()).readValues(CSV_WITH_COMMENTS);
6666

6767
// first row the same
@@ -88,7 +88,7 @@ public void testLeadingComments() throws Exception
8888
// should not be needed but seems to be...
8989
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
9090

91-
MappingIterator<String[]> it = mapper.reader(String[].class)
91+
MappingIterator<String[]> it = mapper.readerFor(String[].class)
9292
.with(mapper.schema().withComments()).readValues("# first\n#second\n1,2\n");
9393

9494
// first row the same
@@ -105,7 +105,7 @@ public void testLeadingComments() throws Exception
105105
public void testCommentsWithHeaderRow() throws Exception
106106
{
107107
CsvMapper mapper = mapperForCsv();
108-
MappingIterator<Map<String,String>> it = mapper.reader(Map.class)
108+
MappingIterator<Map<String,String>> it = mapper.readerFor(Map.class)
109109
.with(mapper.schema().withComments().withHeader())
110110
.readValues("# headers:\nid,value\n# values:\nab#c,#13\n");
111111

@@ -128,7 +128,7 @@ public void testSimpleCommentsWithDefaultProp() throws Exception
128128
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
129129
final String CSV = "# comment!\na,b\n";
130130

131-
MappingIterator<String[]> it = mapper.reader(String[].class)
131+
MappingIterator<String[]> it = mapper.readerFor(String[].class)
132132
.readValues(CSV);
133133
String[] row = it.nextValue();
134134
// assertEquals(2, row.length);

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestParserSequences.java renamed to src/test/java/com/fasterxml/jackson/dataformat/csv/deser/ReadSequencesTest.java

+62-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.util.*;
55

66
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
7+
import com.fasterxml.jackson.core.JsonProcessingException;
8+
import com.fasterxml.jackson.databind.JsonMappingException;
79
import com.fasterxml.jackson.databind.MappingIterator;
810
import com.fasterxml.jackson.databind.ObjectWriter;
911
import com.fasterxml.jackson.dataformat.csv.*;
@@ -12,7 +14,7 @@
1214
* Tests for verifying behavior of enclosing input stream as
1315
* a logical array.
1416
*/
15-
public class TestParserSequences extends ModuleTestBase
17+
public class ReadSequencesTest extends ModuleTestBase
1618
{
1719
@JsonPropertyOrder({"x", "y"})
1820
protected static class Entry {
@@ -65,6 +67,62 @@ public void testAsSequence() throws Exception
6567
it.close();
6668
}
6769

70+
public void testSequenceRecovery() throws Exception
71+
{
72+
CsvMapper mapper = mapperForCsv();
73+
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
74+
MappingIterator<Entry> it = mapper.readerWithSchemaFor(Entry.class).readValues(
75+
"1,2\n3,invalid\n5,6\n1,2,3,5\n13,-4\ngarbage\n");
76+
Entry entry;
77+
78+
assertTrue(it.hasNext());
79+
assertNotNull(entry = it.nextValue());
80+
assertEquals(1, entry.x);
81+
assertEquals(2, entry.y);
82+
assertTrue(it.hasNext());
83+
84+
// second row, invalid:
85+
try {
86+
it.nextValue();
87+
fail("Shouldn't have passed");
88+
} catch (JsonMappingException e) {
89+
verifyException(e, "'invalid': not a valid");
90+
}
91+
92+
// but third is fine again
93+
assertNotNull(entry = it.nextValue());
94+
assertEquals(5, entry.x);
95+
assertEquals(6, entry.y);
96+
97+
// fourth not
98+
assertTrue(it.hasNext());
99+
try {
100+
it.nextValue();
101+
fail("Shouldn't have passed");
102+
} catch (JsonProcessingException e) {
103+
// !!! TODO, maybe: Would be nicer to get a JsonMappingException?
104+
verifyException(e, "Too many entries");
105+
}
106+
107+
// fifth ok
108+
assertTrue(it.hasNext());
109+
assertNotNull(entry = it.nextValue());
110+
assertEquals(13, entry.x);
111+
assertEquals(-4, entry.y);
112+
113+
// and sixth busted again
114+
assertTrue(it.hasNext());
115+
try {
116+
it.nextValue();
117+
fail("Shouldn't have passed");
118+
} catch (JsonMappingException e) {
119+
verifyException(e, "String value 'garbage'");
120+
}
121+
assertFalse(it.hasNext());
122+
it.close();
123+
}
124+
125+
68126
// Test using sequence of entries wrapped in a logical array.
69127
public void testAsWrappedArray() throws Exception
70128
{
@@ -97,7 +155,7 @@ public void testLongerUnwrapped() throws Exception
97155
final int EXPECTED_BYTES = 97640;
98156
assertEquals(EXPECTED_BYTES, bytes.length);
99157

100-
MappingIterator<Entry> it = mapper.reader(Entry.class).with(schema).readValues(bytes, 0, bytes.length);
158+
MappingIterator<Entry> it = mapper.readerFor(Entry.class).with(schema).readValues(bytes, 0, bytes.length);
101159
verifySame(it, entries);
102160
bytes = null;
103161

@@ -106,7 +164,7 @@ public void testLongerUnwrapped() throws Exception
106164
assertEquals(EXPECTED_BYTES, text.length());
107165
it.close();
108166

109-
it = mapper.reader(Entry.class).with(schema).readValues(text);
167+
it = mapper.readerFor(Entry.class).with(schema).readValues(text);
110168
verifySame(it, entries);
111169
it.close();
112170

@@ -118,7 +176,7 @@ public void testRawObjectArrays() throws Exception
118176
CsvMapper mapper = new CsvMapper();
119177
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
120178
final String CSV = "a,b\nc,d\ne,f\n";
121-
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(CSV);
179+
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(CSV);
122180

123181
assertTrue(it.hasNext());
124182
Object[] row = it.next();

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestFiltering.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void testWithJsonView() throws Exception
6969

7070
// plus read back?
7171
final String INPUT = "a,aa,b\n5,6,7\n";
72-
Bean result = mapper.reader(Bean.class).with(schema).withView(ViewB.class).readValue(INPUT);
72+
Bean result = mapper.readerFor(Bean.class).with(schema).withView(ViewB.class).readValue(INPUT);
7373
assertEquals("5", result.a);
7474
// due to filtering, ought to use default
7575
assertEquals("2", result.aa);

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestParser.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private void _testMapsWithLinefeeds(boolean useBytes) throws Exception
136136
+"data41,\"data42 data42\r\ndata42\",data43\n";
137137

138138
CsvSchema cs = CsvSchema.emptySchema().withHeader();
139-
ObjectReader or = mapper.reader(HashMap.class).with(cs);
139+
ObjectReader or = mapper.readerFor(HashMap.class).with(cs);
140140

141141
MappingIterator<Map<String,String>> mi;
142142

@@ -186,7 +186,7 @@ public void testEmptyHandlingForInteger() throws Exception
186186
CsvSchema schema = mapper.typedSchemaFor(Point.class).withoutHeader();
187187

188188
// First: empty value, to be considered as null
189-
Point result = mapper.reader(Point.class).with(schema).readValue(",,\n");
189+
Point result = mapper.readerFor(Point.class).with(schema).readValue(",,\n");
190190
assertEquals(0, result.x);
191191
assertNull(result.y);
192192
assertNull(result.z);
@@ -198,7 +198,7 @@ public void testStringNullHandlingForInteger() throws Exception
198198
CsvSchema schema = mapper.typedSchemaFor(Point.class).withoutHeader();
199199

200200
// First: empty value, to be considered as null
201-
Point result = mapper.reader(Point.class).with(schema).readValue("null,null,null\n");
201+
Point result = mapper.readerFor(Point.class).with(schema).readValue("null,null,null\n");
202202
assertEquals(0, result.x);
203203
assertNull(result.y);
204204
assertNull(result.z);
@@ -211,7 +211,7 @@ public void testIncorrectDups41() throws Exception
211211
CsvSchema schema = CsvSchema.builder().addColumn("Col1").addColumn("Col2")
212212
.addColumn("Col3").build();
213213

214-
MappingIterator<Object> iter = new CsvMapper().reader(Object.class)
214+
MappingIterator<Object> iter = new CsvMapper().readerFor(Object.class)
215215
.with(schema).readValues(INPUT);
216216

217217
Map<?,?> m = (Map<?,?>) iter.next();

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestParserEscapes.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void testEscapesAtStartInUnquoted() throws Exception
5858
final String id = "\\|abcdef"; // doubled for javac
5959
final String desc = "Desc with\\\nlinefeed";
6060
String input = id+"|"+desc+"\n";
61-
Desc result = mapper.reader(schema).withType(Desc.class).readValue(input);
61+
Desc result = mapper.reader(schema).forType(Desc.class).readValue(input);
6262
assertEquals("|abcdef", result.id);
6363
assertEquals("Desc with\nlinefeed", result.desc);
6464
}

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestParserNoSchema.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void testUntypedAsSequence() throws Exception
3232
final String CSV = "1,null\nfoobar\n7,true\n";
3333
CsvParser cp = mapper.getFactory().createParser(CSV);
3434

35-
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(cp);
35+
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(cp);
3636

3737
Object[] row;
3838
assertTrue(it.hasNext());
@@ -63,7 +63,7 @@ public void testUntypedAsObjectArray() throws Exception
6363
CsvMapper mapper = mapperForCsv();
6464
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
6565
// when wrapped as an array, we'll get array of Lists:
66-
Object[] rows = mapper.reader(Object[].class).readValue(
66+
Object[] rows = mapper.readerFor(Object[].class).readValue(
6767
"1,\"xyz\"\n\ntrue,\n"
6868
);
6969
assertEquals(3, rows.length);
@@ -112,7 +112,7 @@ public void testUntypedWithHeaderAsMap() throws Exception
112112
{
113113
CsvMapper mapper = mapperForCsv();
114114
MappingIterator<Map<String,String>> it = mapper
115-
.reader(Map.class)
115+
.readerFor(Map.class)
116116
.with(mapper.schemaWithHeader())
117117
.readValues("a,b\n1,2\n3,4\n");
118118

@@ -145,7 +145,7 @@ public void testUntypedAsSequenceVarLengths() throws Exception
145145
final String CSV = "1,2\n1,2,3,4\n";
146146
CsvParser cp = mapper.getFactory().createParser(CSV);
147147

148-
MappingIterator<String[]> it = mapper.reader(String[].class).readValues(cp);
148+
MappingIterator<String[]> it = mapper.readerFor(String[].class).readValues(cp);
149149

150150
Object[] row;
151151
assertTrue(it.hasNext());
@@ -181,7 +181,7 @@ public void testDelimiterAtBufferBoundary() throws Exception
181181
final String col2 = "H";
182182

183183
CsvParser cp = mapper.getFactory().createParser(col1 + " ," + col2 +"\n" + col2 + "," + col1 + "\n");
184-
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(cp);
184+
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(cp);
185185

186186
Object[] row;
187187

src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TestParserWithHeader.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void testSimpleQuotes() throws Exception
5050
CsvMapper mapper = mapperForCsv();
5151
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
5252
CsvSchema schema = CsvSchema.emptySchema().withHeader();
53-
Entry entry = mapper.reader(Entry.class).with(schema).readValue(
53+
Entry entry = mapper.readerFor(Entry.class).with(schema).readValue(
5454
"name,age,\"cute\" \nLeo,4,true\n");
5555
assertEquals("Leo", entry.name);
5656
assertEquals(4, entry.age);
@@ -62,7 +62,7 @@ public void testSkipFirstDataLine() throws Exception
6262
CsvMapper mapper = mapperForCsv();
6363
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
6464
CsvSchema schema = mapper.schemaFor(Entry.class).withSkipFirstDataRow(true);
65-
MappingIterator<Entry> it = mapper.reader(Entry.class).with(schema).readValues(
65+
MappingIterator<Entry> it = mapper.readerFor(Entry.class).with(schema).readValues(
6666
"12354\n6,Lila,true");
6767
Entry entry;
6868

@@ -149,7 +149,7 @@ public void testInvalidMissingHeader() throws Exception
149149
{
150150
CsvMapper mapper = mapperForCsv();
151151
try {
152-
mapper.reader(Entry.class).with(CsvSchema.emptySchema().withHeader()).readValue(" \nJoseph,57,false");
152+
mapper.readerFor(Entry.class).with(CsvSchema.emptySchema().withHeader()).readValue(" \nJoseph,57,false");
153153
fail("Should have failed with exception");
154154
} catch (Exception e) {
155155
verifyException(e, "Empty header line");

src/test/java/com/fasterxml/jackson/dataformat/csv/ser/JDKSerializationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void testObjectMapper() throws IOException
6262

6363
assertEquals(EXP_CSV, mapper2.writerFor(MyPojo.class)
6464
.with(SCHEMA_POJO).writeValueAsString(p).trim());
65-
MyPojo p2 = mapper2.reader(MyPojo.class).with(SCHEMA_POJO).readValue(EXP_CSV);
65+
MyPojo p2 = mapper2.readerFor(MyPojo.class).with(SCHEMA_POJO).readValue(EXP_CSV);
6666
assertEquals(p.x, p2.x);
6767
assertEquals(p.y, p2.y);
6868

0 commit comments

Comments
 (0)