Skip to content

Commit 82fc626

Browse files
authored
Merge pull request #15 from square/integer-path
Fix serializing when path has integer bits
2 parents 5c3b711 + 9f2c55f commit 82fc626

File tree

5 files changed

+61
-10
lines changed

5 files changed

+61
-10
lines changed

src/Json.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -113,34 +113,34 @@ protected function isEmpty($value) : bool
113113
/**
114114
* Appends the given value to an array of data on the path to serializing to a JSON string
115115
*/
116-
public function appendValue(object $data, $value)
116+
public function appendValue(array &$data, $value)
117117
{
118118
if ($this->omit_empty && $this->isEmpty($value)) {
119119
return;
120120
}
121121
$max = count($this->path)-1;
122-
$d = $data;
122+
$d = &$data;
123123
foreach ($this->path as $i => $pathBit) {
124-
if (property_exists($d, $pathBit) && $i === $max) {
124+
if (array_key_exists($pathBit, $d) && $i === $max) {
125125
throw new \Exception('invalid path: '.json_encode($this->path));
126126
}
127127

128-
if (!property_exists($d, $pathBit) && $i < $max) {
129-
$d->$pathBit = new stdClass;
128+
if (!array_key_exists($pathBit, $d) && $i < $max) {
129+
$d[$pathBit] = [];
130130
}
131131

132132
if ($i < $max) {
133-
$d = $data->$pathBit;
133+
$d = &$d[$pathBit];
134134
}
135135

136136
if ($i === $max) {
137137
if (is_array($value)) {
138-
$d->$pathBit = [];
138+
$d[$pathBit] = [];
139139
foreach ($value as $k => $val) {
140-
$d->$pathBit[$k] = $this->jsonValue($val);
140+
$d[$pathBit][$k] = $this->jsonValue($val);
141141
}
142142
} else {
143-
$d->$pathBit = $this->jsonValue($value);
143+
$d[$pathBit] = $this->jsonValue($value);
144144
}
145145
}
146146
}

src/JsonSerialize.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function toJsonData()
1919
{
2020
$r = RClass::make($this);
2121
$props = $r->getProperties();
22-
$d = new stdClass;
22+
$d = [];
2323
foreach ($props as $prop) {
2424
$attrs = $prop->getAttributes(Json::class, ReflectionAttribute::IS_INSTANCEOF);
2525
if (empty($attrs)) {

tests/DeSerializationTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33

44
use PHPUnit\Framework\TestCase;
55
use ReflectionClass;
6+
use Square\Pjson\Json;
7+
use Square\Pjson\JsonSerialize;
68
use Square\Pjson\Tests\Definitions\BigCat;
79
use Square\Pjson\Tests\Definitions\BigInt;
810
use Square\Pjson\Tests\Definitions\CatalogCategory;
911
use Square\Pjson\Tests\Definitions\CatalogItem;
1012
use Square\Pjson\Tests\Definitions\CatalogObject;
1113
use Square\Pjson\Tests\Definitions\Category;
14+
use Square\Pjson\Tests\Definitions\MenuList;
1215
use Square\Pjson\Tests\Definitions\Schedule;
1316
use Square\Pjson\Tests\Definitions\Privateer;
1417
use Square\Pjson\Tests\Definitions\Stats;
@@ -454,4 +457,21 @@ public function testClassToScalar()
454457
]
455458
], $this->export($stats));
456459
}
460+
461+
public function testIntegerPath()
462+
{
463+
$json = '{
464+
"menus": [
465+
{"main": true, "name": "main-menu"},
466+
{"main": false, "name": "secondary-menu"}
467+
]
468+
}';
469+
470+
$dl = MenuList::fromJsonString($json);
471+
472+
$this->assertEquals([
473+
"@class" => MenuList::class,
474+
"mainMenuName" => "main-menu"
475+
], $this->export($dl));
476+
}
457477
}

tests/Definitions/MenuList.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Square\Pjson\Tests\Definitions;
4+
5+
use Square\Pjson\Json;
6+
use Square\Pjson\JsonSerialize;
7+
8+
class MenuList
9+
{
10+
use JsonSerialize;
11+
12+
#[Json(['menus', 0, 'name'])]
13+
public string $mainMenuName;
14+
}

tests/SerializationTest.php

+17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Square\Pjson\Tests\Definitions\CatalogItem;
1111
use Square\Pjson\Tests\Definitions\CatalogObject;
1212
use Square\Pjson\Tests\Definitions\Category;
13+
use Square\Pjson\Tests\Definitions\MenuList;
1314
use Square\Pjson\Tests\Definitions\Privateer;
1415
use Square\Pjson\Tests\Definitions\Schedule;
1516
use Square\Pjson\Tests\Definitions\Stats;
@@ -226,4 +227,20 @@ public function testClassToScalar()
226227
$stats->toJson()
227228
);
228229
}
230+
231+
public function testIntegerPath()
232+
{
233+
$json = '{
234+
"menus": [
235+
{"main": true, "name": "main-menu"},
236+
{"main": false, "name": "secondary-menu"}
237+
]
238+
}';
239+
240+
$dl = MenuList::fromJsonString($json);
241+
242+
// MenuList doesn't store the entire structure. Only the name of the first menu
243+
// it can however still output all the data it has back into its original shape
244+
$this->assertEquals('{"menus":[{"name":"main-menu"}]}', $dl->toJson());
245+
}
229246
}

0 commit comments

Comments
 (0)