///|
/// Stable JSON output uses declaration order instead of map iteration order.
pub fn Row::to_json_text(self : Row) -> String {
let fields = self.cells.map(cell => {
Json::string(cell.name).stringify() + ":" + cell.value.to_json().stringify()
})
"{" + fields.join(",") + "}"
}
///|
pub fn Table::to_json_text(self : Table) -> String {
"{\"name\":" +
Json::string(self.name).stringify() +
",\"rows\":[" +
self.rows.map(r => r.to_json_text()).join(",") +
"]}"
}
///|
pub fn Dataset::to_json_text(self : Dataset) -> String {
"{\"format\":\"moonfixture.dataset.v1\",\"model\":" +
Json::string(self.model).stringify() +
",\"seed\":" +
Json::string(self.seed.to_string()).stringify() +
",\"algorithm\":" +
Json::string(self.algorithm).stringify() +
",\"reference_time\":" +
Json::string(self.reference_time).stringify() +
",\"tables\":[" +
self.tables.map(t => t.to_json_text()).join(",") +
"]}"
}
///|
pub fn Table::to_ndjson(self : Table) -> String {
let out = StringBuilder()
for row in self.rows {
out.write_string(row.to_json_text())
out.write_char('\n')
}
out.to_string()
}
///|
fn csv_cell(text : String) -> String {
let out = StringBuilder()
let quote = text.contains(",") ||
text.contains("\"") ||
text.contains("\n") ||
text.contains("\r")
if quote {
out.write_char('"')
}
for c in text.iter() {
if c == '"' {
out.write_char('"')
}
out.write_char(c)
}
if quote {
out.write_char('"')
}
out.to_string()
}
///|
/// CSV is an interchange representation; null and empty text both become empty.
pub fn Table::to_csv(self : Table, columns : Array[String]) -> String {
let out = StringBuilder()
out.write_string(columns.map(csv_cell).join(","))
out.write_string("\r\n")
for row in self.rows {
let cells = columns.map(name => {
match row.get(name) {
Some(value) => csv_cell(value.display())
None => ""
}
})
out.write_string(cells.join(","))
out.write_string("\r\n")
}
out.to_string()
}
///|
pub fn Table::batches(
self : Table,
size : Int,
) -> Result[Array[Array[Row]], Issue] {
if size <= 0 {
return Err(
issue("invalid_batch_size", self.name, "Batch size must be positive"),
)
}
let batches : Array[Array[Row]] = []
let mut offset = 0
while offset < self.rows.length() {
let length = size.min(self.rows.length() - offset)
batches.push(self.rows[offset:offset + length].to_owned())
offset += length
}
Ok(batches)
}