annotate vendor/symfony/serializer/Serializer.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Serializer;
Chris@0 13
Chris@0 14 use Symfony\Component\Serializer\Encoder\ChainDecoder;
Chris@0 15 use Symfony\Component\Serializer\Encoder\ChainEncoder;
Chris@17 16 use Symfony\Component\Serializer\Encoder\DecoderInterface;
Chris@0 17 use Symfony\Component\Serializer\Encoder\EncoderInterface;
Chris@17 18 use Symfony\Component\Serializer\Exception\LogicException;
Chris@14 19 use Symfony\Component\Serializer\Exception\NotEncodableValueException;
Chris@14 20 use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
Chris@0 21 use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
Chris@17 22 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
Chris@0 23 use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
Chris@0 24 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * Serializer serializes and deserializes data.
Chris@0 28 *
Chris@0 29 * objects are turned into arrays by normalizers.
Chris@0 30 * arrays are turned into various output formats by encoders.
Chris@0 31 *
Chris@17 32 * $serializer->serialize($obj, 'xml')
Chris@17 33 * $serializer->decode($data, 'xml')
Chris@17 34 * $serializer->denormalize($data, 'Class', 'xml')
Chris@0 35 *
Chris@0 36 * @author Jordi Boggiano <j.boggiano@seld.be>
Chris@0 37 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
Chris@0 38 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
Chris@0 39 * @author Kévin Dunglas <dunglas@gmail.com>
Chris@0 40 */
Chris@0 41 class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
Chris@0 42 {
Chris@0 43 /**
Chris@0 44 * @var Encoder\ChainEncoder
Chris@0 45 */
Chris@0 46 protected $encoder;
Chris@0 47
Chris@0 48 /**
Chris@0 49 * @var Encoder\ChainDecoder
Chris@0 50 */
Chris@0 51 protected $decoder;
Chris@0 52
Chris@0 53 /**
Chris@0 54 * @var array
Chris@0 55 */
Chris@17 56 protected $normalizers = [];
Chris@0 57
Chris@0 58 /**
Chris@0 59 * @var array
Chris@0 60 *
Chris@0 61 * @deprecated since 3.1 will be removed in 4.0
Chris@0 62 */
Chris@17 63 protected $normalizerCache = [];
Chris@0 64
Chris@0 65 /**
Chris@0 66 * @var array
Chris@0 67 *
Chris@0 68 * @deprecated since 3.1 will be removed in 4.0
Chris@0 69 */
Chris@17 70 protected $denormalizerCache = [];
Chris@0 71
Chris@17 72 public function __construct(array $normalizers = [], array $encoders = [])
Chris@0 73 {
Chris@0 74 foreach ($normalizers as $normalizer) {
Chris@0 75 if ($normalizer instanceof SerializerAwareInterface) {
Chris@0 76 $normalizer->setSerializer($this);
Chris@0 77 }
Chris@0 78
Chris@0 79 if ($normalizer instanceof DenormalizerAwareInterface) {
Chris@0 80 $normalizer->setDenormalizer($this);
Chris@0 81 }
Chris@0 82
Chris@0 83 if ($normalizer instanceof NormalizerAwareInterface) {
Chris@0 84 $normalizer->setNormalizer($this);
Chris@0 85 }
Chris@0 86 }
Chris@0 87 $this->normalizers = $normalizers;
Chris@0 88
Chris@17 89 $decoders = [];
Chris@17 90 $realEncoders = [];
Chris@0 91 foreach ($encoders as $encoder) {
Chris@0 92 if ($encoder instanceof SerializerAwareInterface) {
Chris@0 93 $encoder->setSerializer($this);
Chris@0 94 }
Chris@0 95 if ($encoder instanceof DecoderInterface) {
Chris@0 96 $decoders[] = $encoder;
Chris@0 97 }
Chris@0 98 if ($encoder instanceof EncoderInterface) {
Chris@0 99 $realEncoders[] = $encoder;
Chris@0 100 }
Chris@0 101 }
Chris@0 102 $this->encoder = new ChainEncoder($realEncoders);
Chris@0 103 $this->decoder = new ChainDecoder($decoders);
Chris@0 104 }
Chris@0 105
Chris@0 106 /**
Chris@0 107 * {@inheritdoc}
Chris@0 108 */
Chris@17 109 final public function serialize($data, $format, array $context = [])
Chris@0 110 {
Chris@14 111 if (!$this->supportsEncoding($format, $context)) {
Chris@14 112 throw new NotEncodableValueException(sprintf('Serialization for the format %s is not supported', $format));
Chris@0 113 }
Chris@0 114
Chris@14 115 if ($this->encoder->needsNormalization($format, $context)) {
Chris@0 116 $data = $this->normalize($data, $format, $context);
Chris@0 117 }
Chris@0 118
Chris@0 119 return $this->encode($data, $format, $context);
Chris@0 120 }
Chris@0 121
Chris@0 122 /**
Chris@0 123 * {@inheritdoc}
Chris@0 124 */
Chris@17 125 final public function deserialize($data, $type, $format, array $context = [])
Chris@0 126 {
Chris@14 127 if (!$this->supportsDecoding($format, $context)) {
Chris@14 128 throw new NotEncodableValueException(sprintf('Deserialization for the format %s is not supported', $format));
Chris@0 129 }
Chris@0 130
Chris@0 131 $data = $this->decode($data, $format, $context);
Chris@0 132
Chris@0 133 return $this->denormalize($data, $type, $format, $context);
Chris@0 134 }
Chris@0 135
Chris@0 136 /**
Chris@0 137 * {@inheritdoc}
Chris@0 138 */
Chris@17 139 public function normalize($data, $format = null, array $context = [])
Chris@0 140 {
Chris@0 141 // If a normalizer supports the given data, use it
Chris@14 142 if ($normalizer = $this->getNormalizer($data, $format, $context)) {
Chris@0 143 return $normalizer->normalize($data, $format, $context);
Chris@0 144 }
Chris@0 145
Chris@0 146 if (null === $data || is_scalar($data)) {
Chris@0 147 return $data;
Chris@0 148 }
Chris@0 149
Chris@14 150 if (\is_array($data) || $data instanceof \Traversable) {
Chris@17 151 $normalized = [];
Chris@0 152 foreach ($data as $key => $val) {
Chris@0 153 $normalized[$key] = $this->normalize($val, $format, $context);
Chris@0 154 }
Chris@0 155
Chris@0 156 return $normalized;
Chris@0 157 }
Chris@0 158
Chris@14 159 if (\is_object($data)) {
Chris@0 160 if (!$this->normalizers) {
Chris@0 161 throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
Chris@0 162 }
Chris@0 163
Chris@14 164 throw new NotNormalizableValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', \get_class($data)));
Chris@0 165 }
Chris@0 166
Chris@14 167 throw new NotNormalizableValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true)));
Chris@14 168 }
Chris@14 169
Chris@14 170 /**
Chris@14 171 * {@inheritdoc}
Chris@14 172 *
Chris@14 173 * @throws NotNormalizableValueException
Chris@14 174 */
Chris@17 175 public function denormalize($data, $type, $format = null, array $context = [])
Chris@14 176 {
Chris@14 177 if (!$this->normalizers) {
Chris@14 178 throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
Chris@14 179 }
Chris@14 180
Chris@14 181 if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) {
Chris@14 182 return $normalizer->denormalize($data, $type, $format, $context);
Chris@14 183 }
Chris@14 184
Chris@14 185 throw new NotNormalizableValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type));
Chris@0 186 }
Chris@0 187
Chris@0 188 /**
Chris@0 189 * {@inheritdoc}
Chris@0 190 */
Chris@17 191 public function supportsNormalization($data, $format = null/*, array $context = []*/)
Chris@0 192 {
Chris@14 193 if (\func_num_args() > 2) {
Chris@14 194 $context = \func_get_arg(2);
Chris@14 195 } else {
Chris@14 196 if (__CLASS__ !== \get_class($this)) {
Chris@14 197 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@14 198 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@17 199 @trigger_error(sprintf('The "%s()" method will have a third `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@14 200 }
Chris@14 201 }
Chris@14 202
Chris@17 203 $context = [];
Chris@14 204 }
Chris@14 205
Chris@14 206 return null !== $this->getNormalizer($data, $format, $context);
Chris@0 207 }
Chris@0 208
Chris@0 209 /**
Chris@0 210 * {@inheritdoc}
Chris@0 211 */
Chris@17 212 public function supportsDenormalization($data, $type, $format = null/*, array $context = []*/)
Chris@0 213 {
Chris@14 214 if (\func_num_args() > 3) {
Chris@14 215 $context = \func_get_arg(3);
Chris@14 216 } else {
Chris@14 217 if (__CLASS__ !== \get_class($this)) {
Chris@14 218 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@14 219 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@17 220 @trigger_error(sprintf('The "%s()" method will have a fourth `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@14 221 }
Chris@14 222 }
Chris@0 223
Chris@17 224 $context = [];
Chris@14 225 }
Chris@14 226
Chris@14 227 return null !== $this->getDenormalizer($data, $type, $format, $context);
Chris@0 228 }
Chris@0 229
Chris@0 230 /**
Chris@0 231 * Returns a matching normalizer.
Chris@0 232 *
Chris@14 233 * @param mixed $data Data to get the serializer for
Chris@14 234 * @param string $format Format name, present to give the option to normalizers to act differently based on formats
Chris@14 235 * @param array $context Options available to the normalizer
Chris@0 236 *
Chris@0 237 * @return NormalizerInterface|null
Chris@0 238 */
Chris@14 239 private function getNormalizer($data, $format, array $context)
Chris@0 240 {
Chris@0 241 foreach ($this->normalizers as $normalizer) {
Chris@14 242 if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format, $context)) {
Chris@0 243 return $normalizer;
Chris@0 244 }
Chris@0 245 }
Chris@0 246 }
Chris@0 247
Chris@0 248 /**
Chris@0 249 * Returns a matching denormalizer.
Chris@0 250 *
Chris@14 251 * @param mixed $data Data to restore
Chris@14 252 * @param string $class The expected class to instantiate
Chris@14 253 * @param string $format Format name, present to give the option to normalizers to act differently based on formats
Chris@14 254 * @param array $context Options available to the denormalizer
Chris@0 255 *
Chris@0 256 * @return DenormalizerInterface|null
Chris@0 257 */
Chris@14 258 private function getDenormalizer($data, $class, $format, array $context)
Chris@0 259 {
Chris@0 260 foreach ($this->normalizers as $normalizer) {
Chris@14 261 if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $class, $format, $context)) {
Chris@0 262 return $normalizer;
Chris@0 263 }
Chris@0 264 }
Chris@0 265 }
Chris@0 266
Chris@0 267 /**
Chris@0 268 * {@inheritdoc}
Chris@0 269 */
Chris@17 270 final public function encode($data, $format, array $context = [])
Chris@0 271 {
Chris@0 272 return $this->encoder->encode($data, $format, $context);
Chris@0 273 }
Chris@0 274
Chris@0 275 /**
Chris@0 276 * {@inheritdoc}
Chris@0 277 */
Chris@17 278 final public function decode($data, $format, array $context = [])
Chris@0 279 {
Chris@0 280 return $this->decoder->decode($data, $format, $context);
Chris@0 281 }
Chris@0 282
Chris@0 283 /**
Chris@14 284 * {@inheritdoc}
Chris@0 285 */
Chris@17 286 public function supportsEncoding($format/*, array $context = []*/)
Chris@0 287 {
Chris@14 288 if (\func_num_args() > 1) {
Chris@14 289 $context = \func_get_arg(1);
Chris@14 290 } else {
Chris@14 291 if (__CLASS__ !== \get_class($this)) {
Chris@14 292 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@14 293 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@17 294 @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@14 295 }
Chris@14 296 }
Chris@14 297
Chris@17 298 $context = [];
Chris@0 299 }
Chris@0 300
Chris@14 301 return $this->encoder->supportsEncoding($format, $context);
Chris@0 302 }
Chris@0 303
Chris@0 304 /**
Chris@0 305 * {@inheritdoc}
Chris@0 306 */
Chris@17 307 public function supportsDecoding($format/*, array $context = []*/)
Chris@0 308 {
Chris@14 309 if (\func_num_args() > 1) {
Chris@14 310 $context = \func_get_arg(1);
Chris@14 311 } else {
Chris@14 312 if (__CLASS__ !== \get_class($this)) {
Chris@14 313 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@14 314 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@17 315 @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@14 316 }
Chris@14 317 }
Chris@0 318
Chris@17 319 $context = [];
Chris@14 320 }
Chris@14 321
Chris@14 322 return $this->decoder->supportsDecoding($format, $context);
Chris@0 323 }
Chris@0 324 }