Skip to content

Commit

Permalink
feature #23404 [Serializer] AbstractObjectNormalizer: Allow to disabl…
Browse files Browse the repository at this point in the history
…e type enforcement (ogizanagi)

This PR was merged into the 3.4 branch.

Discussion
----------

[Serializer] AbstractObjectNormalizer: Allow to disable type enforcement

| Q             | A
| ------------- | ---
| Branch?       | 3.4 <!-- see comment below -->
| Bug fix?      | no
| New feature?  | yes <!-- don't forget updating src/**/CHANGELOG.md files -->
| BC breaks?    | no
| Deprecations? | no <!-- don't forget updating UPGRADE-*.md files -->
| Tests pass?   | yes (failure unrelated)
| Fixed tickets | N/A <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A

This allows to denormalize simple DTOs with public properties using the property-info component and the `ObjectNormalizer`. The raised exception is not really useful in such cases, as it cannot be easily handled gracefully to build a proper violation response (too generic and no real hint on the complete attribute path for instance).
Instead, I use the validator component to validate my DTOs and the properties' types, get a proper violation list, and build a response from it.

I wasn't really inspired for the `DISABLE_TYPE_ENFORCEMENT` name.

Commits
-------

959ac2a [Serializer] AbstractObjectNormalizer: Allow to disable type enforcement
  • Loading branch information
nicolas-grekas committed Jul 12, 2017
2 parents 21b7fd4 + 959ac2a commit 5f91f74
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Symfony/Component/Serializer/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========

3.4.0
-----

* added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option
to disable throwing an `UnexpectedValueException` on a type mismatch

3.3.0
-----

Expand Down
Expand Up @@ -32,6 +32,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
const ENABLE_MAX_DEPTH = 'enable_max_depth';
const DEPTH_KEY_PATTERN = 'depth_%s::%s';
const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';

private $propertyTypeExtractor;
private $attributesCache = array();
Expand Down Expand Up @@ -286,6 +287,10 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma
}
}

if (!empty($context[self::DISABLE_TYPE_ENFORCEMENT])) {
return $data;
}

throw new UnexpectedValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data)));
}

Expand Down
Expand Up @@ -628,6 +628,16 @@ public function testRejectInvalidKey()
$serializer->denormalize(array('inners' => array('a' => array('foo' => 1))), ObjectOuter::class);
}

public function testDoNotRejectInvalidTypeOnDisableTypeEnforcementContextOption()
{
$extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor()));
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
$serializer = new Serializer(array($normalizer));
$context = array(ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true);

$this->assertSame('foo', $serializer->denormalize(array('number' => 'foo'), JsonNumber::class, null, $context)->number);
}

public function testExtractAttributesRespectsFormat()
{
$normalizer = new FormatAndContextAwareNormalizer();
Expand Down

0 comments on commit 5f91f74

Please sign in to comment.