Skip to content

Commit d0f7642

Browse files
authored
Merge pull request #5 from clue-labs/ndjson
Example and documentation for converting CSV to NDJSON
2 parents 1c4bd21 + 4e8dd75 commit d0f7642

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ that CSV is often used for historial reasons and using CSV to store structured
105105
application data is usually not a good idea nowadays – but exporting to CSV for
106106
known applications is a very reasonable approach.
107107

108+
As an alternative, if you want to process structured data in a more modern
109+
JSON-based format, you may want to use [clue/reactphp-ndjson](https://github.com/clue/reactphp-ndjson)
110+
to process newline-delimited JSON (NDJSON) files (`.ndjson` file extension).
111+
112+
```json
113+
{"name":"Alice","age":30,"comment":"Yes, I like cheese"}
114+
{"name":"Bob","age":50,"comment":"Hello\nWorld!"}
115+
```
116+
108117
## Usage
109118

110119
### Decoder
@@ -329,6 +338,10 @@ This project is released under the permissive [MIT license](LICENSE).
329338
* If you want to learn more about processing streams of data, refer to the documentation of
330339
the underlying [react/stream](https://github.com/reactphp/stream) component.
331340

341+
* If you want to process structured data in a more modern JSON-based format,
342+
you may want to use [clue/reactphp-ndjson](https://github.com/clue/reactphp-ndjson)
343+
to process newline-delimited JSON (NDJSON) files (`.ndjson` file extension).
344+
332345
* If you want to process compressed CSV files (`.csv.gz` file extension)
333346
you may want to use [clue/reactphp-zlib](https://github.com/clue/reactphp-zlib)
334347
on the compressed input stream before passing the decompressed stream to the CSV decoder.

examples/11-csv2ndjson.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
use React\EventLoop\Factory;
4+
use React\Stream\ReadableResourceStream;
5+
use React\Stream\WritableResourceStream;
6+
use Clue\React\Csv\Decoder;
7+
use React\Stream\ThroughStream;
8+
9+
require __DIR__ . '/../vendor/autoload.php';
10+
11+
$loop = Factory::create();
12+
13+
$exit = 0;
14+
$in = new ReadableResourceStream(STDIN, $loop);
15+
$out = new WritableResourceStream(STDOUT, $loop);
16+
$info = new WritableResourceStream(STDERR, $loop);
17+
18+
$delimiter = isset($argv[1]) ? $argv[1] : ',';
19+
20+
$decoder = new Decoder($in, $delimiter);
21+
22+
$headers = array();
23+
$encoder = new ThroughStream(function ($data) use (&$headers) {
24+
return json_encode(array_combine($headers, $data), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n";
25+
});
26+
$encoder->pipe($out);
27+
28+
// first row from decoder will be used as header values, then start piping to encoder
29+
$decoder->once('data', function ($data) use (&$headers, $decoder, $encoder) {
30+
$headers = $data;
31+
$decoder->pipe($encoder);
32+
});
33+
34+
$decoder->on('error', function (Exception $e) use ($info, &$exit) {
35+
$info->write('ERROR: ' . $e->getMessage() . PHP_EOL);
36+
$exit = 1;
37+
});
38+
39+
$info->write('You can pipe/write a valid CSV stream to STDIN' . PHP_EOL);
40+
$info->write('Valid NDJSON (Newline-Delimited JSON) will be forwarded to STDOUT' . PHP_EOL);
41+
$info->write('Invalid CSV will raise an error on STDERR and exit with code 1' . PHP_EOL);
42+
43+
$loop->run();
44+
45+
exit($exit);

0 commit comments

Comments
 (0)