parseGeneric static method

TCsvParseResult parseGeneric(
  1. String content, {
  2. String? delimiter,
})

Parses generic content (CSV, TSV, Semicolon, Pipe, or JSON) into a structured TCsvParseResult.

Implementation

static TCsvParseResult parseGeneric(String content, {String? delimiter}) {
  if (content.trim().isEmpty) {
    return const TCsvParseResult(
      format: TCsvFileFormat.csv,
      headers: [],
      rows: [],
    );
  }

  String text = content;
  if (text.startsWith('\uFEFF')) {
    text = text.substring(1);
  }

  if (isJson(text)) {
    final jsonMaps = parseJson(text);
    if (jsonMaps.isEmpty) {
      return const TCsvParseResult(
        format: TCsvFileFormat.json,
        headers: [],
        rows: [],
      );
    }

    // Collect all unique keys across all maps in order
    final headersSet = <String>{};
    for (final map in jsonMaps) {
      headersSet.addAll(map.keys);
    }
    final headers = headersSet.toList();

    final rows = jsonMaps.map((map) {
      return headers.map((h) => map[h]?.toString() ?? '').toList();
    }).toList();

    return TCsvParseResult(
      format: TCsvFileFormat.json,
      headers: headers,
      rows: rows,
      jsonMaps: jsonMaps,
    );
  }

  // Delimited file
  final effectiveDelimiter = delimiter ?? detectDelimiter(text);
  final format = switch (effectiveDelimiter) {
    '\t' => TCsvFileFormat.tsv,
    ';' => TCsvFileFormat.semicolon,
    '|' => TCsvFileFormat.pipe,
    _ => TCsvFileFormat.csv,
  };

  final rawRows = parseDelimited(text, delimiter: effectiveDelimiter);
  if (rawRows.isEmpty) {
    return TCsvParseResult(
      format: format,
      delimiter: effectiveDelimiter,
      headers: const [],
      rows: const [],
    );
  }

  final headers = rawRows.first;
  final dataRows = rawRows.skip(1).toList();

  return TCsvParseResult(
    format: format,
    delimiter: effectiveDelimiter,
    headers: headers,
    rows: dataRows,
  );
}