Skip to content

Commit

Permalink
Merge pull request #5701 from ballerina-platform/csv-bbes
Browse files Browse the repository at this point in the history
Add Ballerina by examples for`data.csv` module
  • Loading branch information
gimantha authored Oct 2, 2024
2 parents 6a1b06f + 198bd4d commit 78318a8
Show file tree
Hide file tree
Showing 25 changed files with 358 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import ballerina/data.csv;
import ballerina/io;

type Book record {
string name;
string author;
decimal price;
string publishedDate;
};

type BookMinimal record {|
string name;
string author;
|};

const csvFilePath = "./files/csv_file.csv";

public function main() returns error? {
// Write a CSV file.
check io:fileWriteCsv(csvFilePath, [["name", "author", "price", "publishedDate"],
["Effective Java", "Joshua Bloch", "45.99", "2018-01-01"],
["Clean Code", "Robert C. Martin", "37.5", "2008-08-01"]]);

// Read the CSV file as a byte stream.
stream<byte[], error?> bookStream = check io:fileReadBlocksAsStream(csvFilePath);

// Parse as CSV byte stream to an array of records.
Book[] bookArray = check csv:parseStream(bookStream);
io:println(bookArray);

bookStream = check io:fileReadBlocksAsStream(csvFilePath);

// Parse the CSV byte stream as an array of records with data projection.
// Here only the fields specified in the target record type (`name` and `author` fields)
// are included in the constructed value.
BookMinimal[] briefBookArray = check csv:parseStream(bookStream);
io:println(briefBookArray);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Parse CSV byte stream to Ballerina record array

The Ballerina `data.csv` library allows parsing the CSV byte streams as arrays of Ballerina records, making it easier to process CSV data directly from `streams`. This functionality supports data projection, enabling developers to extract and map only the required fields to the target `record` type.

::: code csv_streams_to_record_array.bal :::

::: out csv_streams_to_record_array.out :::
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates the parsing of CSV byte streams into Ballerina record arrays, both with and without data projection.
keywords: ballerina, ballerina by example, bbe, csv, csv byte streams, csv streams, record, record array, parseStream, csv data module, data.csv, data projection, csv to stream
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$ bal run csv_streams_to_record_array.bal
[{"name":"Effective Java","author":"Joshua Bloch","price":45.99,"publishedDate":"2018-01-01"},{"name":"Clean Code","author":"Robert C. Martin","price":37.5,"publishedDate":"2008-08-01"}]
[{"name":"Effective Java","author":"Joshua Bloch"},{"name":"Clean Code","author":"Robert C. Martin"}]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import ballerina/data.csv;
import ballerina/io;

public function main() returns error? {
string csvString = string `name,author,price,publishedDate
Effective Java,Joshua Bloch,45.99,2018-01-01
Clean Code,Robert C. Martin,37.50,2008-08-01`;

// Parse the CSV string as an array of `string` arrays.
string[][] bookArray = check csv:parseString(csvString);
io:println(bookArray);

// Parse the CSV string to an array of `anydata` arrays.
anydata[][] bookArray2 = check csv:parseString(csvString);
io:println(bookArray2);

// Parse the CSV string to an array of `string` arrays with data projection.
// Here only the first two headers are extracted to the resulting array,
// based on the array member size specified in the expected type.
string[][2] bookArray3 = check csv:parseString(csvString);
io:println(bookArray3);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Parse CSV string to arrays

The Ballerina `data.csv` library offers a number of functions for parsing CSV strings to subtypes of `anydata[][]`, enabling developers to effectively parse CSV string data into flexible data structures. Additionally, it provides the option to select specific fields for inclusion in the resulting arrays of `anydata` arrays, allowing developers to extract only the required data.

::: code csv_string_to_anydata_array.bal :::

::: out csv_string_to_anydata_array.out :::
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates the parsing of a CSV string into an array of anydata arrays, both with and without data projection.
keywords: ballerina, ballerina by example, bbe, csv, csv to array, csv string, anydata, anydata array, parseString, csv data module, data.csv, data projection
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
$ bal run csv_string_to_anydata_array.bal
[["Effective Java","Joshua Bloch","45.99","2018-01-01"],["Clean Code","Robert C. Martin","37.50","2008-08-01"]]
[["Effective Java","Joshua Bloch",45.99,"2018-01-01"],["Clean Code","Robert C. Martin",37.5,"2008-08-01"]]
[["Effective Java","Joshua Bloch"],["Clean Code","Robert C. Martin"]]
30 changes: 30 additions & 0 deletions examples/csv-string-to-record-array/csv_string_to_record_array.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import ballerina/data.csv;
import ballerina/io;

type Book record {
string name;
string author;
decimal price;
string publishedDate;
};

type BookMinimal record {|
string name;
string author;
|};

public function main() {
string csvString = string `name,author,price,publishedDate
Effective Java,Joshua Bloch,45.99,2018-01-01
Clean Code,Robert C. Martin,37.50,2008-08-01`;

// Parse CSV string to a array of records.
Book[]|csv:Error bookRecords = csv:parseString(csvString);
io:println(bookRecords);

// Parse CSV string to a array of records with data projection.
// Here only the fields specified in the target record type (`name` and `author` fields)
// are included in the constructed value.
BookMinimal[]|csv:Error briefBookRecords = csv:parseString(csvString);
io:println(briefBookRecords);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Parse CSV string to array of records

The ballerina `data.csv` library offers a range of functions for parsing CSV strings to array of records, enabling developers to parse CSV string data to structured records while allowing for the selection of specific fields within the expected record array.

::: code csv_string_to_record_array.bal :::

::: out csv_string_to_record_array.out :::
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates conversion of CSV string to array of records with and without data projection.
keywords: ballerina, ballerina by example, bbe, csv, csv string, record, record array, parseString, csv data module, data.csv, data projection
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$ bal run csv_string_to_record_array.bal
[{"name":"Effective Java","author":"Joshua Bloch","price":45.99,"publishedDate":"2018-01-01"},{"name":"Clean Code","author":"Robert C. Martin","price":37.5,"publishedDate":"2008-08-01"}]
[{"name":"Effective Java","author":"Joshua Bloch"},{"name":"Clean Code","author":"Robert C. Martin"}]
58 changes: 58 additions & 0 deletions examples/csv-user-configurations/csv_user_configurations.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import ballerina/data.csv;
import ballerina/io;

// Defines the structure of an `Employee` record.
type Employee record {|
int id;
string name;
string department;
|};

// Defines the structure of an `EmployeeDepartment` record.
type EmployeeDepartment record {|
int id;
string department;
|};

public function main() returns error? {
// This CSV string contains `|` separated values and a comment.
// The `"` character in `O\"Connor` value is escaped using the `\` character.
string csvString = string `id|name|department # This is a comment
1|O\"Connor|Engineering
2|Doe|HR
3|Jane|Finance
4|John|Engineering`;

// Defines the options for parsing the CSV string.
// The `|` character is used as the delimiter for separating fields.
// The `\` character is used to escape characters (e.g., quotes) within the data.
// The `#` character indicates the start of a comment, lines starting with `#` will be ignored.
// The second and fourth data rows will be skipped during parsing.
csv:ParseOptions parseOptions = {
delimiter: "|",
escapeChar: "\\",
comment: "#",
skipLines: [2, 4]
};

// Parse the CSV string into an array of `Employee` records with specified options.
Employee[] employees = check csv:parseString(csvString, parseOptions);
io:println(employees);

Employee[] employeeRecords = [
{id: 1, name: "John", department: "Engineering"},
{id: 2, name: "Doe", department: "HR"},
{id: 3, name: "Jane", department: "Finance"},
{id: 4, name: "John", department: "Engineering"}
];

// Defines the options for transforming the `Employee` records.
// The second and fourth data rows will be skipped during transformation.
csv:TransformOptions transformOptions = {
skipLines: [2, 4]
};

// Transform the `employee` records into `EmployeeDepartment` records with specified options.
EmployeeDepartment[] employeeDepartments = check csv:transform(employeeRecords, transformOptions);
io:println(employeeDepartments);
}
7 changes: 7 additions & 0 deletions examples/csv-user-configurations/csv_user_configurations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Handle CSV with custom configurations

Ballerina provides flexible CSV data handling through custom configurations, enabling developers to define delimiters, escape characters, and skip specific lines. This approach allows efficient parsing and transformation of CSV files, streamlining the integration process.

::: code csv_user_configurations.bal :::

::: out csv_user_configurations.out :::
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates how to process CSV data using custom configurations.
keywords: ballerina, ballerina by example, bbe, csv, csv records, record, record array, transform, parseString, csv data module, data.csv, data projection, csv configs, csv configurations
3 changes: 3 additions & 0 deletions examples/csv-user-configurations/csv_user_configurations.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$ bal run csv_user_configurations.bal
[{"id":1,"name":"O"Connor","department":"Engineering"},{"id":3,"name":"Jane","department":"Finance"}]
[{"id":1,"department":"Engineering"},{"id":3,"department":"Finance"}]
49 changes: 49 additions & 0 deletions examples/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -4766,6 +4766,55 @@
}
]
},
{
"title": "CSV data",
"column": 3,
"category": "Common libraries",
"samples": [
{
"name": "Convert CSV string to records",
"url": "csv-string-to-record-array",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
},
{
"name": "Convert CSV string to arrays",
"url": "csv-string-to-anydata-array",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
},
{
"name": "Parse CSV byte streams to records",
"url": "csv-streams-to-record-array",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
},
{
"name": "Parse CSV lists to custom types",
"url": "parse-csv-lists",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
},
{
"name": "Transform CSV records to custom types",
"url": "transform-csv-records-to-custom-types",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
},
{
"name": "Handle CSV with custom configurations",
"url": "csv-user-configurations",
"verifyBuild": true,
"verifyOutput": false,
"isLearnByExample": true
}
]
},
{
"title": "Constraint",
"column": 3,
Expand Down
48 changes: 48 additions & 0 deletions examples/parse-csv-lists/parse_csv_lists.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import ballerina/data.csv;
import ballerina/io;

// Represents the details of an employee.
type Employee record {|
int empId;
string empName;
string department;
float salary;
|};

// Represents the salary details of an employee.
type EmployeeSalary record {|
// This annotation is used to map the empId field in the source CSV record
// to the id field in the target record.
@csv:Name {
value: "empId"
}
int id;
float salary;
|};

public function main() returns error? {
// Sample CSV string array representing employee data.
string[][] csvList = [
["1", "John", "Engineering", "1000.0"],
["2", "Doe", "HR", "2000.0"],
["3", "Jane", "Finance", "3000.0"]
];

// Parse the CSV list into an array of `Employee` records by specifying custom headers.
Employee[] employees = check csv:parseList(csvList, {
customHeaders: ["empId", "empName", "department", "salary"]
});
io:println(employees);

// Parse the CSV list into an array of `EmployeeSalary` records by specifying custom headers.
// Only the fields specified in the EmployeeSalary type (`id` and `salary`)
// are included in the resulting array.
EmployeeSalary[] employeeSalaries = check csv:parseList(csvList, {
customHeaders: ["empId", "empName", "department", "salary"]
});
io:println(employeeSalaries);

// Parse the CSV list into an array of `anydata` arrays.
anydata[][] employeesArray = check csv:parseList(csvList);
io:println(employeesArray);
}
7 changes: 7 additions & 0 deletions examples/parse-csv-lists/parse_csv_lists.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Parse CSV lists to custom types

Ballerina enables parsing CSV lists into various data structures, including custom `record` types and arrays. It facilitates parsing CSV lists into record types with specified fields, allowing for both reshaping of the data and maintaining its original structure.

::: code parse_csv_lists.bal :::

::: out parse_csv_lists.out :::
2 changes: 2 additions & 0 deletions examples/parse-csv-lists/parse_csv_lists.metatags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates the parsing of CSV lists into Ballerina records and arrays, both with and without data projection.
keywords: ballerina, ballerina by example, bbe, csv, csv lists, record, record array, parseList, csv data module, data.csv, data projection, csv to record array
4 changes: 4 additions & 0 deletions examples/parse-csv-lists/parse_csv_lists.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
$ bal run parse_csv_lists.bal
[{"empId":1,"empName":"John","department":"Engineering","salary":1000.0},{"empId":2,"empName":"Doe","department":"HR","salary":2000.0},{"empId":3,"empName":"Jane","department":"Finance","salary":3000.0}]
[{"id":1,"salary":1000.0},{"id":2,"salary":2000.0},{"id":3,"salary":3000.0}]
[[1,"John","Engineering",1000.0],[2,"Doe","HR",2000.0],[3,"Jane","Finance",3000.0]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import ballerina/data.csv;
import ballerina/io;

// Represents the details of an employee.
type Employee record {|
int empId;
string empName;
string department;
decimal salary;
|};

// Represents the salary details of an employee.
type EmployeeSalary record {|
// This annotation is used to map the `empId` field in the source CSV record
// to the `id` field in the target record.
@csv:Name {
value: "empId"
}
int id;
decimal salary;
|};

public function main() returns error? {
Employee[] employees = [
{empId: 1, empName: "John", department: "Engineering", salary: 1000.0},
{empId: 2, empName: "Doe", department: "HR", salary: 2000.0},
{empId: 3, empName: "Jane", department: "Finance", salary: 3000.0}
];

// Transform the `employees` array into an array of `EmployeeSalary` records.
// Only the fields specified in the `EmployeeSalary` type (`id` and `salary`)
// are included in the values in the resulting array.
EmployeeSalary[] employeeSalaries = check csv:transform(employees);
io:println(employeeSalaries);

// Transform the `employees` array into an array of `anydata` arrays.
anydata[][] employeesArray = check csv:transform(employees);
io:println(employeesArray);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Transform CSV records to custom types

Ballerina supports transforming CSV records into various data structures, such as custom records or arrays. It allows users to map CSV records to target types by specifying only the required fields.

::: code transform_csv_records_to_custom_types.bal :::

::: out transform_csv_records_to_custom_types.out :::
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description: This BBE demonstrates the transformation of CSV records into Ballerina arrays, both with and without data projection.
keywords: ballerina, ballerina by example, bbe, csv, csv records, record, record array, transform, csv data module, data.csv, data projection
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$ bal run transform_csv_records_to_custom_types.bal
[{"id":1,"salary":1000.0},{"id":2,"salary":2000.0},{"id":3,"salary":3000.0}]
[[1,"John","Engineering",1000.0],[2,"Doe","HR",2000.0],[3,"Jane","Finance",3000.0]]

0 comments on commit 78318a8

Please sign in to comment.