Skip to content

Commit 584d05f

Browse files
committed
Add string coercion cases from ajv matrix
1 parent a8af693 commit 584d05f

File tree

2 files changed

+92
-15
lines changed

2 files changed

+92
-15
lines changed

src/JsonSchema/Constraints/TypeConstraint.php

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ protected function validateType(&$value, $type, $coerce = false)
217217
}
218218

219219
if ('string' === $type) {
220+
if ($coerce) {
221+
$value = $this->toString($value);
222+
}
223+
220224
return is_string($value);
221225
}
222226

@@ -247,16 +251,14 @@ protected function toBoolean($value)
247251
return false;
248252
}
249253
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
250-
reset($value);
251-
252-
return $this->toBoolean(current($value));
254+
return $this->toBoolean(reset($value));
253255
}
254256

255257
return $value;
256258
}
257259

258260
/**
259-
* Converts a numeric string to a number. For example, "4" becomes 4.
261+
* Converts a numeric string to a number. For example, "4.5" becomes 4.5.
260262
*
261263
* @param mixed $value the value to convert to a number
262264
*
@@ -271,20 +273,18 @@ protected function toNumber($value)
271273
return (int) $value;
272274
}
273275
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
274-
reset($value);
275-
276-
return $this->toNumber(current($value));
276+
return $this->toNumber(reset($value));
277277
}
278278

279279
return $value;
280280
}
281281

282282
/**
283-
* Converts a value to an integer
283+
* Converts a value to an integer. For example, "4" becomes 4.
284284
*
285285
* @param mixed $value
286286
*
287-
* @return mixed
287+
* @return int|mixed
288288
*/
289289
protected function toInteger($value)
290290
{
@@ -297,11 +297,11 @@ protected function toInteger($value)
297297
}
298298

299299
/**
300-
* Converts a value to an array containing that value
300+
* Converts a value to an array containing that value. For example, [4] becomes 4.
301301
*
302302
* @param mixed $value
303303
*
304-
* @return array
304+
* @return array|mixed
305305
*/
306306
protected function toArray($value)
307307
{
@@ -311,4 +311,30 @@ protected function toArray($value)
311311

312312
return $value;
313313
}
314+
315+
/**
316+
* Convert a value to a string representation of that value. For example, null becomes "".
317+
*
318+
* @param mixed $value
319+
*
320+
* @return string|mixed
321+
*/
322+
protected function toString($value)
323+
{
324+
if (is_numeric($value)) {
325+
return "$value";
326+
}
327+
if ($value === true) {
328+
return 'true';
329+
}
330+
if ($value === false) {
331+
return 'false';
332+
}
333+
if (is_null($value)) {
334+
return '';
335+
}
336+
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
337+
return $this->toString(reset($value));
338+
}
339+
}
314340
}

tests/Constraints/CoerciveTest.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,35 @@ public function testValidCoerceCases($input, $schema, $errors = array())
4848
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
4949
$value = json_decode($input);
5050

51+
$this->assertTrue(gettype($value->string) == 'string');
52+
$this->assertTrue(gettype($value->numberString) == 'integer');
53+
$this->assertTrue(gettype($value->boolString) == 'boolean');
54+
$this->assertTrue(gettype($value->boolFalseString) == 'boolean');
55+
$this->assertTrue(gettype($value->nullString) == 'NULL');
56+
$this->assertTrue(gettype($value->arrayString) == 'array');
5157
$this->assertTrue(gettype($value->number) == 'string');
58+
$this->assertTrue(gettype($value->boolNumber) == 'boolean');
59+
$this->assertTrue(gettype($value->nullNumber) == 'NULL');
60+
$this->assertTrue(gettype($value->arrayNumber) == 'array');
5261
$this->assertTrue(gettype($value->integer) == 'string');
62+
$this->assertTrue(gettype($value->negativeInteger) == 'string');
5363
$this->assertTrue(gettype($value->boolean) == 'string');
64+
$this->assertTrue(gettype($value->numberBoolean) == 'integer');
65+
$this->assertTrue(gettype($value->nullBoolean) == 'NULL');
66+
$this->assertTrue(gettype($value->arrayBoolean) == 'array');
67+
$this->assertTrue(gettype($value->array) == 'string');
68+
$this->assertTrue(gettype($value->numberArray) == 'integer');
69+
$this->assertTrue(gettype($value->boolArray) == 'boolean');
70+
$this->assertTrue(gettype($value->nullArray) == 'NULL');
5471

5572
$validator->validate($value, $schema, $checkMode);
5673

74+
$this->assertTrue(gettype($value->string) == 'string');
75+
$this->assertTrue(gettype($value->numberString) == 'string');
76+
$this->assertTrue(gettype($value->boolString) == 'string');
77+
$this->assertTrue(gettype($value->boolFalseString) == 'string');
78+
$this->assertTrue(gettype($value->nullString) == 'string');
79+
$this->assertTrue(gettype($value->arrayString) == 'string');
5780
$this->assertTrue(gettype($value->number) == 'double');
5881
$this->assertTrue(gettype($value->boolNumber) == 'integer');
5982
$this->assertTrue(gettype($value->nullNumber) == 'integer');
@@ -64,12 +87,22 @@ public function testValidCoerceCases($input, $schema, $errors = array())
6487
$this->assertTrue(gettype($value->numberBoolean) == 'boolean');
6588
$this->assertTrue(gettype($value->nullBoolean) == 'boolean');
6689
$this->assertTrue(gettype($value->arrayBoolean) == 'boolean');
90+
$this->assertTrue(gettype($value->array) == 'array');
91+
$this->assertTrue(gettype($value->numberArray) == 'array');
92+
$this->assertTrue(gettype($value->boolArray) == 'array');
93+
$this->assertTrue(gettype($value->nullArray) == 'array');
6794

6895
$this->assertTrue(gettype($value->multitype1) == 'boolean');
6996
$this->assertTrue(gettype($value->multitype2) == 'double');
7097
$this->assertTrue(gettype($value->multitype3) == 'integer');
7198
$this->assertTrue(gettype($value->multitype4) == 'string');
7299

100+
$this->assertTrue($value->string === 'string test');
101+
$this->assertTrue($value->numberString === '45');
102+
$this->assertTrue($value->boolString === 'true');
103+
$this->assertTrue($value->boolFalseString === 'false');
104+
$this->assertTrue($value->nullString === '');
105+
$this->assertTrue($value->arrayString === '45');
73106
$this->assertTrue($value->number === 1.5);
74107
$this->assertTrue($value->boolNumber === 1);
75108
$this->assertTrue($value->nullNumber === 0);
@@ -80,6 +113,10 @@ public function testValidCoerceCases($input, $schema, $errors = array())
80113
$this->assertTrue($value->numberBoolean === true);
81114
$this->assertTrue($value->nullBoolean === false);
82115
$this->assertTrue($value->arrayBoolean === true);
116+
$this->assertTrue($value->array === array('string'));
117+
$this->assertTrue($value->numberArray === array(45));
118+
$this->assertTrue($value->boolArray === array(true));
119+
$this->assertTrue($value->nullArray === array(null));
83120

84121
$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
85122
}
@@ -130,6 +167,11 @@ public function getValidCoerceTests()
130167
array(
131168
'{
132169
"string":"string test",
170+
"numberString":45,
171+
"boolString":true,
172+
"boolFalseString":false,
173+
"nullString":null,
174+
"arrayString":[45],
133175
"number":"1.5",
134176
"boolNumber":true,
135177
"nullNumber":null,
@@ -141,9 +183,10 @@ public function getValidCoerceTests()
141183
"nullBoolean":null,
142184
"arrayBoolean":["true"],
143185
"object":{},
144-
"array":[],
186+
"array":"string",
187+
"numberArray":45,
188+
"boolArray":true,
145189
"nullArray":null,
146-
"stringArray":"string",
147190
"null":null,
148191
"any": "string",
149192
"allOf": "1",
@@ -164,6 +207,11 @@ public function getValidCoerceTests()
164207
"type":"object",
165208
"properties":{
166209
"string":{"type":"string"},
210+
"numberString":{"type":"string"},
211+
"boolString":{"type":"string"},
212+
"boolFalseString":{"type":"string"},
213+
"nullString":{"type":"string"},
214+
"arrayString":{"type":"string"},
167215
"number":{"type":"number"},
168216
"boolNumber":{"type":"number"},
169217
"nullNumber":{"type":"number"},
@@ -176,8 +224,9 @@ public function getValidCoerceTests()
176224
"arrayBoolean":{"type":"boolean"},
177225
"object":{"type":"object"},
178226
"array":{"type":"array"},
227+
"numberArray":{"type":"array"},
228+
"boolArray":{"type":"array"},
179229
"nullArray":{"type":"array"},
180-
"stringArray":{"type":"array"},
181230
"null":{"type":"null"},
182231
"any": {"type":"any"},
183232
"allOf" : {"allOf":[{
@@ -220,7 +269,9 @@ public function getInvalidCoerceTests()
220269
return array(
221270
array( // #0
222271
'{
223-
"string":null
272+
"string":{
273+
"I am":"an object!"
274+
}
224275
}',
225276
'{
226277
"type":"object",

0 commit comments

Comments
 (0)