Given an array of JSON objects or a file that contains JSON objects one after the other, it produces a CSV file with one row per JSON processed. In order to transform a JSON object into a CSV row, this library "flattens" the objects, converting them into equivalent ones without nested objects or arrays. The rules used for flattening objects are configurable, but by default an object like this:
json
{"a": {"b": [1,2,3]}}
is transformed into the flattened JSON object:
json
{
"a.b.0": 1,
"a.b.1": 2,
"a.b.2": 3
}
and then used to generate the following CSV output:
csv
a.b.0,a.b.1,a.b.2
1,2,3
This library relies on
flatten-json-object
for JSON object flattering and csv
for CSV file generation.
Please check their respective documentation if you want to adjust how the output looks.
{"a": {"b": 1}} {"a.b": 2}
results by default in an error.{}
(when not a top level object), []
or Null
results in an empty CSV
field.Read
implementer```rust use csv; use flattenjsonobject::ArrayFormatting; use flattenjsonobject::Flattener; use jsonobjectsto_csv::Json2Csv; use std::io::{Read, Write}; use std::str;
// Anything supported by the Flattener
object is possible.
let flattener = Flattener::new()
.setkeyseparator(".")
.setarrayformatting(ArrayFormatting::Surrounded{
start: "[".tostring(),
end: "]".tostring()
})
.setpreserveemptyarrays(false)
.setpreserveemptyobjects(false);
// The output can be anything that implements Write
. In this example we use a vector but
// this could be a File
.
let mut output = Vec::
// Anything that implements Read
. Usually a file, but we will use a byte array in this example.
let input = r#"{"a": {"b": 1}} {"c": [2]} {"d": []} {"e": {}}"#.as_bytes();
// The CSV rows that we should get from this input and config. Note that since we are not
// preserving empty arrays or objects d
and e
are not part of the final headers.
// However, an empty row is generate for their object. If empty objects and arrays were
// preserved both e
and d
would be part of the headers, but their column would be empty.
let expected = ["a.b,c[0]", "1,", ",2", ",", ","];
// Here we can configure another field separator, like ;
or use any other CSV builder
// configuration.
let csvwriter = csv::WriterBuilder::new()
.delimiter(b',')
.fromwriter(&mut output);
Json2Csv::new(flattener).convertfromreader(input, csv_writer)?;
asserteq!(str::fromutf8(&output)?, expected.join("\n") + "\n"); ```
```rust use csv; use flattenjsonobject::ArrayFormatting; use flattenjsonobject::Flattener; use jsonobjectstocsv::Json2Csv; use serdejson::json; use std::str;
// We changed the array formatting and we preserve empty arrays and objects now, compared to // the previous example. let flattener = Flattener::new() .setkeyseparator(".") .setarrayformatting(ArrayFormatting::Plain) .setpreserveemptyarrays(true) .setpreserveemptyobjects(true);
// The output can be anything that implements Write
. In this example we use a vector but
// this could be a File
.
let mut output = Vec::
let input = [ json!({"a": {"b": 1}}), json!({"c": [2]}), json!({"d": []}), json!({"e": {}}) ];
// This time the separator is ;
let csvwriter = csv::WriterBuilder::new()
.delimiter(b';')
.fromwriter(&mut output);
// The CSV rows that we should get from this input and config. We are preserving empty arrays
// and objects so d
and e
are part of the final headers. Since they are empty and no other
// object has those headers these columns have no value in any of the rows.
let expected = ["a.b;c.0;d;e", "1;;;", ";2;;", ";;;", ";;;"];
Json2Csv::new(flattener).convertfromarray(&input, csv_writer)?;
asserteq!(str::fromutf8(&output)?, expected.join("\n") + "\n"); ```