How to parse a CSV string in Dart
Turn CSV text into rows, with the awkward parts of the format handled for you.
Install#
dart pub add csv_plusimport 'package:csv_plus/csv_plus.dart';Decode a string#
import 'package:csv_plus/csv_plus.dart';
void main() {
final codec = CsvCodec();
final rows = codec.decode('name,age\nAlice,30\nBob,25');
for (final row in rows) {
print(row);
}
// [name, age]
// [Alice, 30]
// [Bob, 25]
}Values come back typed. 30 is an int, not the string "30". See type inference for how that is decided and how to override it.
The parts of CSV that usually break parsers#
A field wrapped in quotes may contain the delimiter, a line break, or an escaped quote. All three are handled:
final rows = codec.decode('name,note\n"Smith, Alice","said ""hello""\nand left"');
rows[1][0]; // Smith, Alice
rows[1][1]; // said "hello"
// and leftThat second field contains a real newline and still belongs to one row, which is why splitting CSV on \n yourself goes wrong on real exports.
Malformed input#
By default the parser recovers from damage and gives you what it can. When you would rather know, turn on strict mode:
final strict = CsvCodec(CsvConfig(strict: true));
strict.decode('"unterminated'); // throws CsvParseExceptionThere is a lenient decoder too, for input you know is untidy:
codec.decodeFlexible(' a , b '); // trims, recovers bad quotesSkipping a preamble#
Exports often start with comment lines or a title block before the real header.
final codec = CsvCodec(CsvConfig(comment: '#', hasHeader: true));
codec.decode('# export 2026-07-17\nname,score\nAlice,95');
// [[Alice, 95]]comment only matches at the start of a line, so a # inside a quoted value stays content. skipRows drops leading rows before the header is read, and maxRows caps how many data rows you load.