Skip to main content

JSON2CSV

Converts an array of JSON objects into CSV. Provides custom mapping of column names and merging of column values (resolves to first found in priority order), as well as custom delimiter and column/row/key joiners. Context attributes can be added to all rows and column-specific value replacements may be defined.

import { tools } from 'tods-competition-factory';

const config = {
includeTransformAccessors, // optional boolean - transform accessors are included with columnAccessors
removeEmptyColumns, // optional boolean - remove columns which contain no values
columnAccessors, // optional - array of column accessors to include [ 'includeThis', 'andThis' ]
columnTransform, // optional - multiple generated column names can resolve to a single custom column, e.g. { 'newColumnName': ['oldColumn1', 'oldColumn2' ]}
columnMap, // optional - simple mapping from generated columnName to custom columnName, e.g. { 'columnName': 'newColumnName' }
functionMap, // optional - transform values, e.g. { 'columnName': (value) => value }
valuesMap, // optional - map values for specified columns, e.g. { 'columnName': { 'value': 'mappedValue '}}
sortOrder // optional - e.g. ['columnName1', 'columnName2'] // determine order of csv columns
context, // optional - object defining values which should be added to all rows, e.g. { 'columnName': 'columnValue '}
delimiter, // optional - defaults to '"'
columnJoiner, // optional - defines how CSV columns are joined; defaults to ','
rowJoiner, // optional - defines how CSV lines are joined; defaults to '\r\n'
keyJoiner, // optional - defines how flattened column names are constructed; defaults to '.'
};
const arrayOfJSON = [{ a: 1 }, { b: 2 }];
const csv = tools.JSON2CSV(arrayOfJSON, config);
note

columnTransform mapped array elements are sensitive to order and will resolve to the first matching value

columnMap should not contain new columnName(s) that are columnTransform keys

Example: Converting MatchUps to CSV

The following example demonstrates converting tournament matchUps to CSV format. This pattern is useful for exporting match results, generating reports, or integrating with external systems.

Setup

Generate tournament data with SINGLES and DOUBLES draws, complete all matches, and extract matchUps:

import { mocksEngine, tournamentEngine, tools } from 'tods-competition-factory';

// Generate tournament with completed matches
const drawProfiles = [
{ drawSize: 8, eventType: 'DOUBLES', matchUpFormat: 'SET3-S:4/TB7-F:TB10' },
{ drawSize: 8, drawType: 'ROUND_ROBIN' },
];

const { tournamentRecord } = mocksEngine.generateTournamentRecord({
completeAllMatchUps: true,
drawProfiles,
});

// Get all matchUps from the tournament
const { matchUps } = tournamentEngine
.setState(tournamentRecord)
.allTournamentMatchUps();

Configuration

The config object extracts specific columns and transforms nested participant data. The columnTransform uses priority-based resolution, falling back to participantName when individualParticipants (for doubles) are not present:

const config = {
rowJoiner: '|',
delimiter: '',
includeTransformAccessors: true,

// Basic matchUp properties to include
columnAccessors: ['matchUpType', 'matchUpFormat', 'endDate', 'roundName'],

// Transform nested participant data into flat columns
// Arrays resolve to first found value (priority order)
columnTransform: {
scoreString: ['score.scoreStringSide1'],

// Side 1 participants (handles both singles and doubles)
side1Participant1: [
'sides.0.participant.individualParticipants.0.participantName', // Doubles: first player
'sides.0.participant.participantName', // Singles: player name
],
side1Participant2: [
'sides.0.participant.individualParticipants.1.participantName' // Doubles: second player
],

// Side 2 participants (handles both singles and doubles)
side2Participant1: [
'sides.1.participant.individualParticipants.0.participantName', // Doubles: first player
'sides.1.participant.participantName', // Singles: player name
],
side2Participant2: [
'sides.1.participant.individualParticipants.1.participantName' // Doubles: second player
],
},
};

Convert to CSV

const csv = tools.JSON2CSV(matchUps, config);

Result Format

The resulting CSV will have columns in this order:

matchUpType|matchUpFormat|endDate|roundName|scoreString|side1Participant1|side1Participant2|side2Participant1|side2Participant2
SINGLES|SET3-S:4/TB7-F:TB10|2024-01-15|Round 1|7-5 6-4|John Smith||Jane Doe|
DOUBLES|SET3-S:4/TB7-F:TB10|2024-01-15|Round 1|6-3 7-6(5)|Alice Brown|Bob White|Carol Green|Dan Black

Key Features:

  • Singles matches leave participant2 columns empty
  • Doubles matches populate all four participant columns
  • The | delimiter is used for easy visual parsing
  • Nested JSON paths are flattened into column names
  • Priority-based resolution handles both singles and doubles with a single config

Common Use Cases

Export for spreadsheets:

const config = {
columnJoiner: ',',
delimiter: '"',
rowJoiner: '\n',
// ... column configuration
};

Custom column ordering:

const config = {
sortOrder: ['roundName', 'side1Participant1', 'side2Participant1', 'scoreString'],
// ... other configuration
};

Add context to all rows:

const config = {
context: {
tournamentName: 'US Open 2024',
eventName: 'Men\'s Singles',
},
// ... other configuration
};