Skip to content

Commit b8df35d

Browse files
RobinvanderVlietcweiske
authored andcommitted
Support "?type" syntax for nullable types
In addition to "int|null", JsonMapper now also supports "?int" - a syntax that was added to PHP in versino 7.1.0 ("Nullable type syntactic sugar"). Resolves: #235
1 parent 45d6745 commit b8df35d

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

README.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ Supported type names
251251
- ``Suit:string|Suit:int`` - exception will be thrown if the JSON value is not present in the enum
252252
- Nullable types:
253253

254-
- ``int|null`` - will be ``null`` if the value in JSON is
254+
- ``int|null`` or ``?int`` - will be ``null`` if the value in JSON is
255255
``null``, otherwise it will be an integer
256-
- ``Contact|null`` - will be ``null`` if the value in JSON is
256+
- ``Contact|null`` or ``?Contact`` - will be ``null`` if the value in JSON is
257257
``null``, otherwise it will be an object of type ``Contact``
258258

259259
ArrayObjects and extending classes are treated as arrays.
@@ -327,7 +327,7 @@ parameters into the call.
327327
Nullables
328328
---------
329329
JsonMapper throws an exception when a JSON property is ``null``,
330-
unless the PHP class property has a nullable type - e.g. ``Contact|null``.
330+
unless the PHP class property has a nullable type - e.g. ``Contact|null`` or ``?Contact``.
331331

332332
If your API contains many fields that may be ``null`` and you do not want
333333
to make all your type definitions nullable, set:

src/JsonMapper.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,8 @@ protected function hasVariadicArrayType($accessor)
857857
*/
858858
protected function isNullable($type)
859859
{
860-
return stripos('|' . $type . '|', '|null|') !== false;
860+
return stripos('|' . $type . '|', '|null|') !== false
861+
|| strpos('|' . $type, '|?') !== false;
861862
}
862863

863864
/**
@@ -873,7 +874,7 @@ protected function removeNullable($type)
873874
return null;
874875
}
875876
return substr(
876-
str_ireplace('|null|', '|', '|' . $type . '|'),
877+
str_ireplace(['|null|', '|?'], '|', '|' . $type . '|'),
877878
1, -1
878879
);
879880
}

tests/SimpleTest.php

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,40 +122,80 @@ public function testMapSimpleMixed()
122122
/**
123123
* Test for "@var int|null" with int value
124124
*/
125-
public function testMapSimpleNullableInt()
125+
public function testMapSimpleNullableIntWithInt()
126126
{
127127
$jm = new JsonMapper();
128128
$sn = $jm->map(
129-
json_decode('{"pnullable":0}'),
129+
json_decode('{"pnullableInt":0}'),
130130
new JsonMapperTest_Simple()
131131
);
132-
$this->assertSame(0, $sn->pnullable);
132+
$this->assertSame(0, $sn->pnullableInt);
133133
}
134134

135135
/**
136136
* Test for "@var int|null" with null value
137137
*/
138-
public function testMapSimpleNullableNull()
138+
public function testMapSimpleNullableIntWithNull()
139139
{
140140
$jm = new JsonMapper();
141141
$sn = $jm->map(
142-
json_decode('{"pnullable":null}'),
142+
json_decode('{"pnullableInt":null}'),
143143
new JsonMapperTest_Simple()
144144
);
145-
$this->assertNull($sn->pnullable);
145+
$this->assertNull($sn->pnullableInt);
146146
}
147147

148148
/**
149-
* Test for "@var int|null" with string value
149+
* Test for "@var int|null" with string value (force cast)
150150
*/
151-
public function testMapSimpleNullableWrong()
151+
public function testMapSimpleNullableIntWithWrongType()
152152
{
153153
$jm = new JsonMapper();
154154
$sn = $jm->map(
155-
json_decode('{"pnullable":"12345"}'),
155+
json_decode('{"pnullableInt":"12345"}'),
156156
new JsonMapperTest_Simple()
157157
);
158-
$this->assertSame(12345, $sn->pnullable);
158+
$this->assertSame(12345, $sn->pnullableInt);
159+
}
160+
161+
/**
162+
* Test for "@var ?string" with string value
163+
*/
164+
public function testMapSimpleNullableStringWithString()
165+
{
166+
$jm = new JsonMapper();
167+
$sn = $jm->map(
168+
json_decode('{"pnullableString":"test"}'),
169+
new JsonMapperTest_Simple()
170+
);
171+
$this->assertSame('test', $sn->pnullableString);
172+
}
173+
174+
/**
175+
* Test for "@var ?string" with null value
176+
*/
177+
public function testMapSimpleNullableStringWithNull()
178+
{
179+
$jm = new JsonMapper();
180+
$sn = $jm->map(
181+
json_decode('{"pnullableString":null}'),
182+
new JsonMapperTest_Simple()
183+
);
184+
$this->assertNull($sn->pnullableString);
185+
$this->assertEquals(null, $sn->pnullableString);
186+
}
187+
188+
/**
189+
* Test for "@var ?string" with int value (force cast)
190+
*/
191+
public function testMapSimpleNullableStringWithWrongType()
192+
{
193+
$jm = new JsonMapper();
194+
$sn = $jm->map(
195+
json_decode('{"pnullableString":0}'),
196+
new JsonMapperTest_Simple()
197+
);
198+
$this->assertSame('0', $sn->pnullableString);
159199
}
160200

161201
/**

tests/support/JsonMapperTest/Simple.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ class JsonMapperTest_Simple
4545
/**
4646
* @var int|null
4747
*/
48-
public $pnullable;
48+
public $pnullableInt;
49+
50+
/**
51+
* @var ?string
52+
*/
53+
public $pnullableString;
4954

5055
/**
5156
* @var float

0 commit comments

Comments
 (0)