Skip to content

Commit 644aba8

Browse files
committed
modified the conversion method for json to csv to make it healthier where there may exist different properties for each object.
1 parent d567361 commit 644aba8

File tree

10 files changed

+101
-58
lines changed

10 files changed

+101
-58
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ $ composer test
129129

130130
## Known Issues
131131

132-
Currently, it is assumed that each object shares the same properties while converting JSON to CSV. So if one object has a property that the other one does not have, then it will be a major problem.
132+
Currently, there are not any issues that are known.
133133

134134
## Contributing
135135

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
}
1313
],
1414
"require": {
15-
"php" : "~7.0"
15+
"php" : "~7.0",
16+
"ext-json": "*"
1617
},
1718
"require-dev": {
1819
"phpunit/phpunit" : "~5.0|~6.0"

src/AbstractFile.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public function __construct($filepath)
3535
*/
3636
public function convertAndDownload($filename = null, $exit = true)
3737
{
38-
header('Content-disposition: attachment; filename=' . ($filename ?? $this->filename) . '.' . $this->conversion['extension']);
38+
$filename = $filename ?? $this->filename;
39+
header('Content-disposition: attachment; filename=' . $filename . '.' . $this->conversion['extension']);
3940
header('Content-type: ' . $this->conversion['type']);
4041
echo $this->convert();
4142
if ($exit === true) {
@@ -48,23 +49,23 @@ public function convertAndDownload($filename = null, $exit = true)
4849
*
4950
* @return bool|int
5051
*/
51-
public function convertAndSave($path) : int
52+
public function convertAndSave($path): int
5253
{
5354
return file_put_contents($path, $this->convert());
5455
}
5556

5657
/**
5758
* @return string
5859
*/
59-
public function getData() : string
60+
public function getData(): string
6061
{
6162
return $this->data;
6263
}
6364

6465
/**
6566
* @return string
6667
*/
67-
public function getFilename() : string
68+
public function getFilename(): string
6869
{
6970
return $this->filename;
7071
}
@@ -75,7 +76,7 @@ public function getFilename() : string
7576
*
7677
* @return array
7778
*/
78-
public function setConversionKey($key, $value) : array
79+
public function setConversionKey($key, $value): array
7980
{
8081
$this->conversion[$key] = $value;
8182
return $this->conversion;
@@ -84,5 +85,5 @@ public function setConversionKey($key, $value) : array
8485
/**
8586
* @return string
8687
*/
87-
abstract public function convert() : string;
88+
abstract public function convert(): string;
8889
}

src/File/Csv.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,37 @@ class Csv extends AbstractFile
99
/**
1010
* @var array
1111
*/
12-
protected $conversion = ['extension' => 'json', 'type' => 'application/json', 'options' => 0, 'delimiter' => ',', 'enclosure' => '"', 'escape' => '\\'];
12+
protected $conversion = [
13+
'extension' => 'json',
14+
'type' => 'application/json',
15+
'options' => 0,
16+
'delimiter' => ',',
17+
'enclosure' => '"',
18+
'escape' => '\\'
19+
];
1320

1421
/**
1522
* @return string
1623
*/
17-
public function convert() : string
24+
public function convert(): string
1825
{
1926
$data = explode("\n", $this->data);
20-
$keys = str_getcsv(array_shift($data), $this->conversion['delimiter'], $this->conversion['enclosure'], $this->conversion['escape']);
27+
$keys = str_getcsv(
28+
array_shift($data),
29+
$this->conversion['delimiter'],
30+
$this->conversion['enclosure'],
31+
$this->conversion['escape']
32+
);
2133
return json_encode(array_map(function ($line) use ($keys) {
22-
return array_combine($keys, str_getcsv($line, $this->conversion['delimiter'], $this->conversion['enclosure'], $this->conversion['escape']));
34+
return array_combine(
35+
$keys,
36+
str_getcsv(
37+
$line,
38+
$this->conversion['delimiter'],
39+
$this->conversion['enclosure'],
40+
$this->conversion['escape']
41+
)
42+
);
2343
}, $data), $this->conversion['options']);
2444
}
2545
}

src/File/Json.php

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,48 +9,54 @@ class Json extends AbstractFile
99
/**
1010
* @var array
1111
*/
12-
protected $conversion = ['extension' => 'csv', 'type' => 'text/csv', 'delimiter' => ',', 'enclosure' => '"', 'escape' => '\\'];
12+
protected $conversion = [
13+
'extension' => 'csv',
14+
'type' => 'text/csv',
15+
'delimiter' => ',',
16+
'enclosure' => '"',
17+
'escape' => '\\',
18+
'null' => null
19+
];
1320

1421
/**
1522
* @return string
1623
*/
17-
public function convert() : string
24+
public function convert(): string
1825
{
19-
$data_decoded = json_decode($this->data, true);
20-
$data_flattened = array_map(function ($d) {
26+
$flattened = array_map(function ($d) {
2127
return $this->flatten($d);
22-
}, $data_decoded);
23-
24-
$keys = [];
25-
foreach ($data_flattened as $entry_flattened) {
26-
foreach ($entry_flattened as $key => $value) {
27-
$keys[$key] = true;
28-
}
29-
}
30-
31-
$data_unified = [];
32-
foreach ($data_flattened as $entry_flattened) {
33-
$entry_unified = [];
34-
foreach ($keys as $key => $foo) {
35-
$entry_unified[$key] = array_key_exists($key, $entry_flattened) ? $entry_flattened[$key] : null;
36-
}
37-
$data_unified[] = $entry_unified;
38-
}
39-
40-
return $this->toCsvString($data_unified);
28+
}, json_decode($this->data, true));
29+
// create an array with all of the keys where each has a null value
30+
$default = $this->getArrayOfNulls($flattened);
31+
// merge default with the actual data so that non existent keys will have null values
32+
return $this->toCsvString(array_map(function ($d) use ($default) {
33+
return array_merge($default, $d);
34+
}, $flattened));
4135
}
4236

4337
/**
4438
* @param array $data
4539
*
4640
* @return string
4741
*/
48-
protected function toCsvString(array $data) : string
42+
protected function toCsvString(array $data): string
4943
{
50-
$f = fopen('php://temp', 'w');
51-
fputcsv($f, array_keys(current($data)), $this->conversion['delimiter'], $this->conversion['enclosure'], $this->conversion['escape']);
44+
$f = fopen('php://temp', 'wb');
45+
fputcsv(
46+
$f,
47+
array_keys(current($data)),
48+
$this->conversion['delimiter'],
49+
$this->conversion['enclosure'],
50+
$this->conversion['escape']
51+
);
5252
foreach ($data as $row) {
53-
fputcsv($f, $row, $this->conversion['delimiter'], $this->conversion['enclosure'], $this->conversion['escape']);
53+
fputcsv(
54+
$f,
55+
$row,
56+
$this->conversion['delimiter'],
57+
$this->conversion['enclosure'],
58+
$this->conversion['escape']
59+
);
5460
}
5561
rewind($f);
5662
$csv = stream_get_contents($f);
@@ -65,7 +71,7 @@ protected function toCsvString(array $data) : string
6571
*
6672
* @return array
6773
*/
68-
protected function flatten(array $array = [], $prefix = '', array $result = []) : array
74+
protected function flatten(array $array = [], $prefix = '', array $result = []): array
6975
{
7076
foreach ($array as $key => $value) {
7177
if (\is_array($value)) {
@@ -76,4 +82,15 @@ protected function flatten(array $array = [], $prefix = '', array $result = [])
7682
}
7783
return $result;
7884
}
85+
86+
/**
87+
* @param $flattened
88+
*
89+
* @return array
90+
*/
91+
protected function getArrayOfNulls($flattened): array
92+
{
93+
$keys = array_keys(array_merge(...$flattened));
94+
return array_fill_keys($keys, $this->conversion['null']);
95+
}
7996
}

tests/JsonTest.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ public function testConversionAndDownload()
4848
/**
4949
* @group json-conversion-test
5050
*/
51-
public function testConversionDynamicFormat()
51+
public function testMixedProperties()
5252
{
53-
$json = new Json(__DIR__ . '/data/dynamicFormat.json');
54-
$result = ($json->convert());
55-
$this->assertEquals(file_get_contents(__DIR__ . '/data/dynamicFormatResult.csv'), $result);
53+
$json = new Json(__DIR__ . '/data/mixed-properties.json');
54+
$result = $json->convert();
55+
$this->assertStringEqualsFile(__DIR__ . '/data/mixed-properties.csv', $result);
5656
}
5757

58-
5958
/**
6059
* @return \OzdemirBurak\JsonCsv\File\Json
6160
*/

tests/data/dynamicFormat.json

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/data/dynamicFormatResult.csv

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/data/mixed-properties.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a,b,c_d,c_e,c,d
2+
0,1,1,2,,
3+
3,,,,4,5

tests/data/mixed-properties.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[
2+
{
3+
"a": 0,
4+
"b": 1,
5+
"c": {
6+
"d": 1,
7+
"e": 2
8+
}
9+
},
10+
{
11+
"a": 3,
12+
"c": 4,
13+
"d": 5
14+
}
15+
]

0 commit comments

Comments
 (0)