Skip to content

Commit bb014e4

Browse files
committed
Add CHECK_MODE_REQUIRE_DEFAULTS
If CHECK_MODE_REQUIRE_DEFAULTS is set, then only apply defaults if they are marked as required.
1 parent f638716 commit bb014e4

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ third argument to `Validator::validate()`, or can be provided as the third argum
187187
| `Constraint::CHECK_MODE_TYPE_CAST` | Enable fuzzy type checking for associative arrays and objects |
188188
| `Constraint::CHECK_MODE_COERCE_TYPES` | Convert data types to match the schema where possible |
189189
| `Constraint::CHECK_MODE_APPLY_DEFAULTS` | Apply default values from the schema if not set |
190+
| `Constraint::CHECK_MODE_REQUIRE_DEFAULTS` | Only apply defaults when they are required |
190191
| `Constraint::CHECK_MODE_EXCEPTIONS` | Throw an exception immediately if validation fails |
191192

192193
Please note that using `Constraint::CHECK_MODE_COERCE_TYPES` or `Constraint::CHECK_MODE_APPLY_DEFAULTS`

src/JsonSchema/Constraints/Constraint.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ abstract class Constraint extends BaseConstraint implements ConstraintInterface
3030
const CHECK_MODE_COERCE_TYPES = 0x00000004;
3131
const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
3232
const CHECK_MODE_EXCEPTIONS = 0x00000010;
33+
const CHECK_MODE_REQUIRE_DEFAULTS = 0x00000020;
3334

3435
/**
3536
* Bubble down the path

src/JsonSchema/Constraints/UndefinedConstraint.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,23 @@ protected function validateCommonProperties(&$value, $schema = null, JsonPointer
113113
// Apply default values from schema
114114
if ($this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
115115
if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
116+
$v4Required = isset($schema->required) ? $schema->required : array();
116117
// $value is an object or assoc array, and properties are defined - treat as an object
117118
foreach ($schema->properties as $currentProperty => $propertyDefinition) {
118119
if (!LooseTypeCheck::propertyExists($value, $currentProperty) && isset($propertyDefinition->default)) {
120+
// Don't apply non-required defaults if running in required-only mode
121+
if (
122+
$this->factory->getConfig(self::CHECK_MODE_REQUIRE_DEFAULTS) &&
123+
!in_array($currentProperty, $v4Required, true) && // draft-04 required
124+
!(// draft-03 required
125+
isset($propertyDefinition->required) &&
126+
!is_array($propertyDefinition->required) &&
127+
$propertyDefinition->required
128+
)
129+
) {
130+
continue;
131+
}
132+
// assign default value
119133
if (is_object($propertyDefinition->default)) {
120134
LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
121135
} else {

tests/Constraints/DefaultPropertiesTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,37 @@ public function testLeaveBasicTypesAlone()
164164
$schema = json_decode('{"items":[{"type":"string","default":"valueOne"}]}');
165165
$this->assertEquals('"ThisIsAString"', json_encode($input));
166166
}
167+
168+
public function testRequiredOnlyDraft04()
169+
{
170+
$input = json_decode('{}');
171+
$schema = json_decode('{
172+
"properties": {
173+
"propertyOne": {"default": "valueOne"},
174+
"propertyTwo": {"default": "valueTwo"}
175+
},
176+
"required": ["propertyTwo"]
177+
}');
178+
179+
$validator = new Validator();
180+
$validator->validate($input, $schema, Constraint::CHECK_MODE_APPLY_DEFAULTS | Constraint::CHECK_MODE_REQUIRE_DEFAULTS);
181+
182+
$this->assertEquals('{"propertyTwo":"valueTwo"}', json_encode($input));
183+
}
184+
185+
public function testRequiredOnlyDraft03()
186+
{
187+
$input = json_decode('{}');
188+
$schema = json_decode('{
189+
"properties": {
190+
"propertyOne": {"default": "valueOne"},
191+
"propertyTwo": {"default": "valueTwo", "required": true}
192+
}
193+
}');
194+
195+
$validator = new Validator();
196+
$validator->validate($input, $schema, Constraint::CHECK_MODE_APPLY_DEFAULTS | Constraint::CHECK_MODE_REQUIRE_DEFAULTS);
197+
198+
$this->assertEquals('{"propertyTwo":"valueTwo"}', json_encode($input));
199+
}
167200
}

0 commit comments

Comments
 (0)