├── .run
└── phpunit.run.xml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── META.md
├── README.md
├── UPGRADING.md
├── composer.json
├── doc
├── LICENSE
├── conf.py
├── configuration.rst
├── cookbook.rst
├── cookbook
│ ├── arrays.rst
│ ├── exclusion_strategies.rst
│ ├── object_constructor.rst
│ └── stdclass.rst
├── event_system.rst
├── handlers.rst
├── index.rst
├── logo-small.png
├── logo.png
├── reference.rst
├── reference
│ ├── annotations.rst
│ ├── xml_reference.rst
│ └── yml_reference.rst
├── requirements.txt
└── usage.rst
├── phpbench.json
├── phpstan.neon.dist
├── rector.php
└── src
├── AbstractVisitor.php
├── Accessor
├── AccessorStrategyInterface.php
└── DefaultAccessorStrategy.php
├── Annotation
├── AccessType.php
├── Accessor.php
├── AccessorOrder.php
├── AnnotationUtilsTrait.php
├── DeprecatedReadOnly.php
├── Discriminator.php
├── Exclude.php
├── ExclusionPolicy.php
├── Expose.php
├── Groups.php
├── Inline.php
├── MaxDepth.php
├── PostDeserialize.php
├── PostSerialize.php
├── PreSerialize.php
├── ReadOnly.php
├── ReadOnlyProperty.php
├── SerializedName.php
├── SerializerAttribute.php
├── Since.php
├── SkipWhenEmpty.php
├── Type.php
├── UnionDiscriminator.php
├── Until.php
├── Version.php
├── VirtualProperty.php
├── XmlAttribute.php
├── XmlAttributeMap.php
├── XmlCollection.php
├── XmlDiscriminator.php
├── XmlElement.php
├── XmlKeyValuePairs.php
├── XmlList.php
├── XmlMap.php
├── XmlNamespace.php
├── XmlRoot.php
└── XmlValue.php
├── ArrayTransformerInterface.php
├── Builder
├── CallbackDriverFactory.php
├── DefaultDriverFactory.php
├── DocBlockDriverFactory.php
└── DriverFactoryInterface.php
├── Construction
├── DoctrineObjectConstructor.php
├── ObjectConstructorInterface.php
└── UnserializeObjectConstructor.php
├── Context.php
├── ContextFactory
├── CallableContextFactory.php
├── CallableDeserializationContextFactory.php
├── CallableSerializationContextFactory.php
├── DefaultDeserializationContextFactory.php
├── DefaultSerializationContextFactory.php
├── DeserializationContextFactoryInterface.php
└── SerializationContextFactoryInterface.php
├── DeserializationContext.php
├── EventDispatcher
├── Event.php
├── EventDispatcher.php
├── EventDispatcherInterface.php
├── EventSubscriberInterface.php
├── Events.php
├── LazyEventDispatcher.php
├── ObjectEvent.php
├── PreDeserializeEvent.php
├── PreSerializeEvent.php
└── Subscriber
│ ├── DoctrineProxySubscriber.php
│ ├── EnumSubscriber.php
│ └── SymfonyValidatorValidatorSubscriber.php
├── Exception
├── CircularReferenceDetectedException.php
├── Exception.php
├── ExcludedClassException.php
├── ExpressionLanguageRequiredException.php
├── InvalidArgumentException.php
├── InvalidMetadataException.php
├── LogicException.php
├── NonCastableTypeException.php
├── NonFloatCastableTypeException.php
├── NonIntCastableTypeException.php
├── NonStringCastableTypeException.php
├── NonVisitableTypeException.php
├── NotAcceptableException.php
├── ObjectConstructionException.php
├── RuntimeException.php
├── SkipHandlerException.php
├── UninitializedPropertyException.php
├── UnsupportedFormatException.php
├── ValidationFailedException.php
└── XmlErrorException.php
├── Exclusion
├── DepthExclusionStrategy.php
├── DisjunctExclusionStrategy.php
├── ExclusionStrategyInterface.php
├── ExpressionLanguageExclusionStrategy.php
├── GroupsExclusionStrategy.php
└── VersionExclusionStrategy.php
├── Expression
├── CompilableExpressionEvaluatorInterface.php
├── Expression.php
├── ExpressionEvaluator.php
└── ExpressionEvaluatorInterface.php
├── Functions.php
├── GraphNavigator.php
├── GraphNavigator
├── DeserializationGraphNavigator.php
├── Factory
│ ├── DeserializationGraphNavigatorFactory.php
│ ├── GraphNavigatorFactoryInterface.php
│ └── SerializationGraphNavigatorFactory.php
└── SerializationGraphNavigator.php
├── GraphNavigatorInterface.php
├── Handler
├── ArrayCollectionHandler.php
├── ConstraintViolationHandler.php
├── DateHandler.php
├── EnumHandler.php
├── FormErrorHandler.php
├── HandlerRegistry.php
├── HandlerRegistryInterface.php
├── IteratorHandler.php
├── LazyHandlerRegistry.php
├── StdClassHandler.php
├── SubscribingHandlerInterface.php
├── SymfonyUidHandler.php
└── UnionHandler.php
├── JsonDeserializationStrictVisitor.php
├── JsonDeserializationVisitor.php
├── JsonSerializationVisitor.php
├── Metadata
├── ClassMetadata.php
├── Driver
│ ├── AbstractDoctrineTypeDriver.php
│ ├── AnnotationDriver.php
│ ├── AnnotationOrAttributeDriver.php
│ ├── AttributeDriver.php
│ ├── AttributeDriver
│ │ └── AttributeReader.php
│ ├── DefaultValuePropertyDriver.php
│ ├── DocBlockDriver.php
│ ├── DocBlockDriver
│ │ └── DocBlockTypeResolver.php
│ ├── DoctrinePHPCRTypeDriver.php
│ ├── DoctrineTypeDriver.php
│ ├── EnumPropertiesDriver.php
│ ├── ExpressionMetadataTrait.php
│ ├── NullDriver.php
│ ├── TypedPropertiesDriver.php
│ ├── XmlDriver.php
│ └── YamlDriver.php
├── ExpressionPropertyMetadata.php
├── PropertyMetadata.php
├── StaticPropertyMetadata.php
└── VirtualPropertyMetadata.php
├── Naming
├── CamelCaseNamingStrategy.php
├── IdenticalPropertyNamingStrategy.php
├── PropertyNamingStrategyInterface.php
└── SerializedNameAnnotationStrategy.php
├── NullAwareVisitorInterface.php
├── Ordering
├── AlphabeticalPropertyOrderingStrategy.php
├── CustomPropertyOrderingStrategy.php
├── IdenticalPropertyOrderingStrategy.php
└── PropertyOrderingInterface.php
├── SerializationContext.php
├── Serializer.php
├── SerializerBuilder.php
├── SerializerInterface.php
├── Twig
├── SerializerBaseExtension.php
├── SerializerExtension.php
├── SerializerRuntimeExtension.php
└── SerializerRuntimeHelper.php
├── Type
├── Exception
│ ├── Exception.php
│ ├── InvalidNode.php
│ └── SyntaxError.php
├── Lexer.php
├── Parser.php
├── ParserInterface.php
└── Type.php
├── Visitor
├── DeserializationVisitorInterface.php
├── Factory
│ ├── DeserializationVisitorFactory.php
│ ├── JsonDeserializationVisitorFactory.php
│ ├── JsonSerializationVisitorFactory.php
│ ├── SerializationVisitorFactory.php
│ ├── XmlDeserializationVisitorFactory.php
│ └── XmlSerializationVisitorFactory.php
└── SerializationVisitorInterface.php
├── VisitorInterface.php
├── XmlDeserializationVisitor.php
└── XmlSerializationVisitor.php
/.run/phpunit.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 |
3 | Thank you for contributing!
4 |
5 | Before we can merge your Pull-Request here are some guidelines that you need to follow.
6 | These guidelines exist not to annoy you, but to keep the code base clean, unified and future proof.
7 |
8 | ## Coding Standard
9 |
10 | This project uses [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) to enforce coding standards.
11 | The coding standard rules are defined in the **phpcs.xml.dist** file (part of this repository).
12 | The project follows a relaxed version of the Doctrine Coding standards v4.
13 |
14 | Your Pull-Request must be compliant with the said standard.
15 | To check your code you can run `vendor/bin/phpcs`. This command will give you a list of violations in your code (if any).
16 | The most common errors can be automatically fixed just by running `vendor/bin/phpcbf`.
17 |
18 | ## Dependencies
19 |
20 | We're using [`composer/composer`](https://github.com/composer/composer) to manage dependencies
21 |
22 | ## Unit-Tests
23 |
24 | Please try to add a test for your pull-request. This project uses [PHPUnit](https://phpunit.de/) as testing framework.
25 |
26 | You can run the unit-tests by calling `vendor/bin/phpunit`.
27 |
28 | New features without tests can't be merged.
29 |
30 |
31 | ## Documentation
32 |
33 | The documentation is stored in the `doc` folder and is written using the [rST](http://docutils.sourceforge.net/rst.html) language.
34 | If you are adding a new feature, you must update the documentation.
35 |
36 | To test doc rendering before submitting your PR, you will need [Sphinx](http://www.sphinx-doc.org/en/stable/).
37 |
38 | To install `Sphinx` just run:
39 |
40 | ```bash
41 | pip install --requirement doc/requirements.txt --user
42 | ```
43 |
44 | When that is done, just run:
45 |
46 | ```bash
47 | cd doc && sphinx-build -W -b html -d _build/doctrees . _build/html
48 | ```
49 |
50 | ## CI
51 |
52 | We automatically run your pull request through [Github Actions](https://github.com/schmittjoh/serializer/actions).
53 | If you break the tests, we cannot merge your code,
54 | so please make sure that your code is working before opening up a Pull-Request.
55 |
56 | ## Issues and Bugs
57 |
58 | To create a new issue, you can use the GitHub issue tracking system.
59 | Please try to avoid opening support-related tickets. For support related questions please use more appropriate
60 | channels as Q&A platforms (such as Stackoverflow), Forums, Local PHP user groups.
61 |
62 | If you are a Symfony user, please try to distinguish between issues related to the Bundle and issues related to this
63 | library.
64 |
65 | ## Getting merged
66 |
67 | Please allow us time to review your pull requests.
68 | We will give our best to review everything as fast as possible, but cannot always live up to our own expectations.
69 |
70 | Please, write [commit messages that make
71 | sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
72 | and [rebase your branch](http://git-scm.com/book/en/Git-Branching-Rebasing)
73 | before submitting your Pull Request.
74 |
75 | One may ask you to [squash your
76 | commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html)
77 | too. This is used to "clean" your Pull Request before merging it (we don't want
78 | commits such as "fix tests", "fix 2", "fix 3", etc.).
79 |
80 | Pull requests without tests most probably will not be merged.
81 | Documentation PRs obviously do not require tests.
82 |
83 | Thank you very much again for your contribution!
84 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Johannes M. Schmitt
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/META.md:
--------------------------------------------------------------------------------
1 | # Generating changelog
2 |
3 | Use: https://github.com/skywinder/Github-Changelog-Generator
4 |
5 | ```bash
6 | github_changelog_generator --user=schmittjoh --project=serializer --pull-requests --no-compare-link -t GITHUB-TOKEN
7 | ```
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > # UKRAINE NEEDS YOUR HELP NOW!
2 | >
3 | > On 24 February 2022, Russian [President Vladimir Putin ordered an invasion of Ukraine by Russian Armed Forces](https://www.bbc.com/news/world-europe-60504334).
4 | >
5 | > Your support is urgently needed.
6 | >
7 | > - Donate to the volunteers. Here is the volunteer fund helping the Ukrainian army to provide all the necessary equipment:
8 | > https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi or https://savelife.in.ua/en/donate/
9 | > - Triple-check social media sources. Russian disinformation is attempting to coverup and distort the reality in Ukraine.
10 | > - Help Ukrainian refugees who are fleeing Russian attacks and shellings: https://www.globalcitizen.org/en/content/ways-to-help-ukraine-conflict/
11 | > - Put pressure on your political representatives to provide help to Ukraine.
12 | > - Believe in the Ukrainian people, they will not surrender, they don't have another Ukraine.
13 | >
14 | > THANK YOU!
15 | ----
16 |
17 | # jms/serializer
18 |
19 | [![GitHub Actions][GA Image]][GA Link]
20 | [![Packagist][Packagist Image]][Packagist Link]
21 |
22 | 
23 |
24 | ## Introduction
25 |
26 | This library allows you to (de-)serialize data of any complexity. Currently, it supports XML and JSON.
27 |
28 | It also provides you with a rich tool-set to adapt the output to your specific needs.
29 |
30 | Built-in features include:
31 |
32 | - (De-)serialize data of any complexity; circular references and complex exclusion strategies are handled gracefully.
33 | - Supports many built-in PHP types (such as dates, intervals)
34 | - Integrates with Doctrine ORM, et. al.
35 | - Supports versioning, e.g. for APIs
36 | - Configurable via XML, YAML, or Annotations
37 |
38 |
39 | ## Documentation
40 |
41 | Learn more about the serializer in its [documentation](http://jmsyst.com/libs/serializer).
42 |
43 | ## Notes
44 |
45 | You are browsing the code for the 3.x version, if you are interested in the 1.x or 2.x version,
46 | check the [1.x][1.x] and [2.x][2.x] branches.
47 |
48 | The version `3.x` is the supported version (`master` branch).
49 | The `1.x` and `2.x` versions are not supported anymore.
50 |
51 | For the `1.x` and `2.x` branches there will be no additional feature releases.
52 | Security issues will be fixed till the 1st January 2020 and
53 | only critical bugs might receive fixes until the 1st September 2019.
54 |
55 | Instructions on how to upgrade to 3.x are available in the [UPGRADING][UPGRADING] document.
56 |
57 | ## Professional Support
58 |
59 | For eventual paid support please write an email to [goetas@gmail.com](mailto:goetas@gmail.com).
60 |
61 |
62 | [CHANGELOG]: https://github.com/schmittjoh/serializer/blob/master/CHANGELOG.md
63 | [UPGRADING]: https://github.com/schmittjoh/serializer/blob/master/UPGRADING.md
64 |
65 | [GA Image]: https://github.com/schmittjoh/serializer/workflows/CI/badge.svg
66 |
67 | [GA Link]: https://github.com/schmittjoh/serializer/actions?query=workflow%3A%22CI%22+branch%3Amaster
68 |
69 | [Packagist Image]: https://img.shields.io/packagist/v/jms/serializer.svg
70 |
71 | [Packagist Link]: https://packagist.org/packages/jms/serializer
72 |
73 | [1.x]: https://github.com/schmittjoh/serializer/tree/1.x
74 | [2.x]: https://github.com/schmittjoh/serializer/tree/2.x
75 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jms/serializer",
3 | "type": "library",
4 | "description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.",
5 | "keywords": [
6 | "serialization",
7 | "deserialization",
8 | "json",
9 | "jaxb",
10 | "xml"
11 | ],
12 | "homepage": "http://jmsyst.com/libs/serializer",
13 | "license": "MIT",
14 | "authors": [
15 | {
16 | "name": "Johannes M. Schmitt",
17 | "email": "schmittjoh@gmail.com"
18 | },
19 | {
20 | "name": "Asmir Mustafic",
21 | "email": "goetas@gmail.com"
22 | }
23 | ],
24 | "require": {
25 | "php": "^7.4 || ^8.0",
26 | "doctrine/instantiator": "^1.3.1 || ^2.0",
27 | "doctrine/lexer": "^2.0 || ^3.0",
28 | "jms/metadata": "^2.6",
29 | "phpstan/phpdoc-parser": "^1.20 || ^2.0"
30 | },
31 | "suggest": {
32 | "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.",
33 | "symfony/cache": "Required if you like to use cache functionality.",
34 | "symfony/uid": "Required if you'd like to serialize UID objects.",
35 | "symfony/yaml": "Required if you'd like to use the YAML metadata format."
36 | },
37 | "require-dev": {
38 | "ext-pdo_sqlite": "*",
39 | "doctrine/annotations": "^1.14 || ^2.0",
40 | "slevomat/coding-standard": "dev-master#f2cc4c553eae68772624ffd7dd99022343b69c31 as 8.11.9999",
41 | "doctrine/coding-standard": "^12.0",
42 | "doctrine/orm": "^2.14 || ^3.0",
43 | "doctrine/persistence": "^2.5.2 || ^3.0",
44 | "doctrine/phpcr-odm": "^1.5.2 || ^2.0",
45 | "jackalope/jackalope-doctrine-dbal": "^1.3",
46 | "ocramius/proxy-manager": "^1.0 || ^2.0",
47 | "phpbench/phpbench": "^1.0",
48 | "phpstan/phpstan": "^2.0",
49 | "phpunit/phpunit": "^9.0 || ^10.0 || ^11.0",
50 | "psr/container": "^1.0 || ^2.0",
51 | "rector/rector": "^1.0.0 || ^2.0@dev",
52 | "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
53 | "symfony/expression-language": "^5.4 || ^6.0 || ^7.0",
54 | "symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
55 | "symfony/form": "^5.4 || ^6.0 || ^7.0",
56 | "symfony/translation": "^5.4 || ^6.0 || ^7.0",
57 | "symfony/uid": "^5.4 || ^6.0 || ^7.0",
58 | "symfony/validator": "^5.4 || ^6.0 || ^7.0",
59 | "symfony/yaml": "^5.4 || ^6.0 || ^7.0",
60 | "twig/twig": "^1.34 || ^2.4 || ^3.0"
61 | },
62 | "autoload": {
63 | "psr-4": {
64 | "JMS\\Serializer\\": "src/"
65 | }
66 | },
67 | "autoload-dev": {
68 | "psr-4": {
69 | "JMS\\Serializer\\Tests\\": "tests/"
70 | }
71 | },
72 | "config": {
73 | "sort-packages": true,
74 | "allow-plugins": {
75 | "composer/package-versions-deprecated": true,
76 | "dealerdirect/phpcodesniffer-composer-installer": true
77 | }
78 | },
79 | "extra": {
80 | "branch-alias": {
81 | "dev-master": "3.x-dev"
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys, os
4 |
5 | # -- General configuration -----------------------------------------------------
6 |
7 | # Add any Sphinx extension module names here, as strings. They can be extensions
8 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
9 | extensions = ['sensio.sphinx.configurationblock', 'sensio.sphinx.phpcode']
10 |
11 | # Add any paths that contain templates here, relative to this directory.
12 | templates_path = ['_templates']
13 |
14 | # The suffix of source filenames.
15 | source_suffix = '.rst'
16 |
17 | # The master toctree document.
18 | master_doc = 'index'
19 |
20 | # List of patterns, relative to source directory, that match files and
21 | # directories to ignore when looking for source files.
22 | exclude_patterns = ['_build']
23 |
24 | # The name of the Pygments (syntax highlighting) style to use.
25 | pygments_style = 'sphinx'
26 |
27 | # This will be used when using the shorthand notation
28 | highlight_language = 'php'
29 |
30 | # -- Options for HTML output ---------------------------------------------------
31 | import sphinx_rtd_theme
32 |
33 | # The theme to use for HTML and HTML Help pages. See the documentation for
34 | # a list of builtin themes.
35 | html_theme = 'sphinx_rtd_theme'
36 |
37 | # Add any paths that contain custom themes here, relative to this directory.
38 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
39 |
40 | # Output file base name for HTML help builder.
41 | htmlhelp_basename = 'doc'
42 |
--------------------------------------------------------------------------------
/doc/cookbook.rst:
--------------------------------------------------------------------------------
1 | Cookbook
2 | ========
3 |
4 | .. toctree ::
5 | :glob:
6 |
7 | cookbook/*
--------------------------------------------------------------------------------
/doc/cookbook/arrays.rst:
--------------------------------------------------------------------------------
1 | Serializing arrays and hashes
2 | =============================
3 |
4 | Introduction
5 | ------------
6 | Serializing arrays and hashes (a concept that in PHP has not explicit boundaries)
7 | can be challenging. The serializer offers via ``@Type`` annotation different options
8 | to configure its behavior, but if we try to serialize directly an array
9 | (not as a property of an object), we need to use context information to determine the
10 | array "type"
11 |
12 | Examples
13 | --------
14 |
15 | In case of a JSON serialization:
16 |
17 | .. code-block :: php
18 |
19 | serialize([1, 2]); // [1, 2]
23 | $serializer->serialize(['a', 'b']); // ['a', 'b']
24 | $serializer->serialize(['c' => 'd']); // {"c" => "d"}
25 |
26 | // same as default (let the PHP's json_encode function decide)
27 | $serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array')); // [1, 2]
28 | $serializer->serialize([1 => 2], SerializationContext::create()->setInitialType('array')); // {"1": 2}
29 | $serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array')); // ['a', 'b']
30 | $serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array')); // {"c" => "d"}
31 |
32 | // typehint as strict array, keys will be always discarded
33 | $serializer->serialize([], SerializationContext::create()->setInitialType('array')); // []
34 | $serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array')); // [1, 2]
35 | $serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array')); // ['a', 'b']
36 | $serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array')); // ["d"]
37 |
38 | // typehint as hash, keys will be always considered
39 | $serializer->serialize([], SerializationContext::create()->setInitialType('array')); // {}
40 | $serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array')); // {"0" : 1, "1" : 2}
41 | $serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array')); // {"0" : "a", "1" : "b"}
42 | $serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array')); // {"c" : "d"}
43 |
44 |
45 | .. note ::
46 |
47 | This applies only for the JSON serialization.
48 |
--------------------------------------------------------------------------------
/doc/cookbook/object_constructor.rst:
--------------------------------------------------------------------------------
1 | Object constructor
2 | ==================
3 |
4 | Deserialize on existing objects
5 | -------------------------------
6 |
7 | By default, a brand new instance of target class is created during deserialization. To deserialize into an existing object, you need to perform the following steps.
8 |
9 |
10 | 1. Create new class which implements ObjectConstructorInterface
11 |
12 | .. code-block:: php
13 |
14 | fallbackConstructor = $fallbackConstructor;
32 | }
33 |
34 | public function construct(DeserializationVisitorInterface $visitor, ClassMetadata $metadata, $data, array $type, DeserializationContext $context): ?object
35 | {
36 | if ($context->hasAttribute(self::ATTRIBUTE)) {
37 | return $context->getAttribute(self::ATTRIBUTE);
38 | }
39 |
40 | return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type, $context);
41 | }
42 | }
43 |
44 |
45 | 2. Register ExistingObjectConstructor.
46 |
47 | You should pass ExistingObjectConstructor to DeserializationGraphNavigatorFactory constructor.
48 |
49 |
50 | 3. Add special attribute to DeserializationContext
51 |
52 | .. code-block:: php
53 |
54 | $context = DeserializationContext::create();
55 | $context->setAttribute('deserialization-constructor-target', $document);
56 | $serializer->deserialize($data, get_class($document), 'json');
57 |
--------------------------------------------------------------------------------
/doc/cookbook/stdclass.rst:
--------------------------------------------------------------------------------
1 | stdClass
2 | ========
3 |
4 | The serializer offers support for serializing ``stdClass`` objects, however the use of
5 | ``stdClass`` objects is discouraged.
6 |
7 | The current implementation serializes all the properties of a ``stdClass`` object in
8 | the order they appear.
9 |
10 | There are many known limitations when dealing with ``stdClass`` objects.
11 | More in detail, it is not possible to:
12 |
13 | - change serialization order of properties
14 | - apply per-property exclusion policies
15 | - specify any extra serialization information for properties that are part of the ``stdClass`` object, as serialization name, type, xml structure and so on
16 | - deserialize data into ``stdClass`` objects
17 |
--------------------------------------------------------------------------------
/doc/event_system.rst:
--------------------------------------------------------------------------------
1 | Event System
2 | ============
3 |
4 | The serializer dispatches different events during the serialization, and
5 | deserialization process which you can use to hook in and alter the default
6 | behavior.
7 |
8 | Register an Event Listener, or Subscriber
9 | -----------------------------------------
10 | The difference between listeners, and subscribers is that listener do not know to which events they listen
11 | while subscribers contain that information. Thus, subscribers are easier to share, and re-use. Listeners
12 | on the other hand, can be simple callables and do not require a dedicated class.
13 |
14 | .. code-block :: php
15 |
16 | class MyEventSubscriber implements JMS\Serializer\EventDispatcher\EventSubscriberInterface
17 | {
18 | public static function getSubscribedEvents()
19 | {
20 | return array(
21 | array(
22 | 'event' => 'serializer.pre_serialize',
23 | 'method' => 'onPreSerialize',
24 | 'class' => 'AppBundle\\Entity\\SpecificClass', // if no class, subscribe to every serialization
25 | 'format' => 'json', // optional format
26 | 'priority' => 0, // optional priority
27 | ),
28 | );
29 | }
30 |
31 | public function onPreSerialize(JMS\Serializer\EventDispatcher\PreSerializeEvent $event)
32 | {
33 | // do something
34 | }
35 | }
36 |
37 | $builder
38 | ->configureListeners(function(JMS\Serializer\EventDispatcher\EventDispatcher $dispatcher) {
39 | $dispatcher->addListener('serializer.pre_serialize',
40 | function(JMS\Serializer\EventDispatcher\PreSerializeEvent $event) {
41 | // do something
42 | }
43 | );
44 |
45 | $dispatcher->addSubscriber(new MyEventSubscriber());
46 | })
47 | ;
48 |
49 | Events
50 | ------
51 |
52 | serializer.pre_serialize
53 | ~~~~~~~~~~~~~~~~~~~~~~~~
54 | This is dispatched before a type is visited. You have access to the visitor,
55 | data, and type. Listeners may modify the type that is being used for
56 | serialization.
57 |
58 | **Event Object**: ``JMS\Serializer\EventDispatcher\PreSerializeEvent``
59 |
60 | serializer.post_serialize
61 | ~~~~~~~~~~~~~~~~~~~~~~~~~
62 | This is dispatched right before a type is left. You can for example use this
63 | to add additional data for an object that you normally do not save inside
64 | objects such as links.
65 |
66 | **Event Object**: ``JMS\Serializer\EventDispatcher\ObjectEvent``
67 |
68 | serializer.pre_deserialize
69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
70 |
71 | .. versionadded : 0.12
72 | Event was added
73 |
74 | This is dispatched before an object is deserialized. You can use this to
75 | modify submitted data, or modify the type that is being used for deserialization.
76 |
77 | **Event Object**: ``JMS\Serializer\EventDispatcher\PreDeserializeEvent``
78 |
79 | serializer.post_deserialize
80 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
81 | This is dispatched after a type is processed. You can use it to normalize
82 | submitted data if you require external services for example, or also to
83 | perform validation of the submitted data.
84 |
85 | **Event Object**: ``JMS\Serializer\EventDispatcher\ObjectEvent``
86 |
--------------------------------------------------------------------------------
/doc/handlers.rst:
--------------------------------------------------------------------------------
1 | Handlers
2 | ========
3 |
4 | Introduction
5 | ------------
6 | Handlers allow you to change the serialization, or deserialization process
7 | for a single type/format combination.
8 |
9 | Handlers are simple callback which receive three arguments: the visitor,
10 | the data, and the type.
11 |
12 | Simple Callables
13 | ----------------
14 | You can register simple callables on the builder object::
15 |
16 | $builder
17 | ->configureHandlers(function(JMS\Serializer\Handler\HandlerRegistry $registry) {
18 | $registry->registerHandler('serialization', 'MyObject', 'json',
19 | function($visitor, MyObject $obj, array $type) {
20 | return $obj->getName();
21 | }
22 | );
23 | })
24 | ;
25 |
26 | .. note ::
27 |
28 | Be aware that when you call `configureHandlers` default handlers (like `DateHandler`)
29 | won't be added and you will have to call `addDefaultHandlers` on the Builder
30 |
31 | Subscribing Handlers
32 | --------------------
33 | Subscribing handlers contain the configuration themselves which makes them easier to share with other users,
34 | and easier to set-up in general::
35 |
36 | use JMS\Serializer\Handler\SubscribingHandlerInterface;
37 | use JMS\Serializer\GraphNavigator;
38 | use JMS\Serializer\JsonSerializationVisitor;
39 | use JMS\Serializer\JsonDeserializationVisitor;
40 | use JMS\Serializer\Context;
41 |
42 | class MyHandler implements SubscribingHandlerInterface
43 | {
44 | public static function getSubscribingMethods()
45 | {
46 | return [
47 | [
48 | 'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
49 | 'format' => 'json',
50 | 'type' => 'DateTime',
51 | 'method' => 'serializeDateTimeToJson',
52 | ],
53 | [
54 | 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
55 | 'format' => 'json',
56 | 'type' => 'DateTime',
57 | 'method' => 'deserializeDateTimeToJson',
58 | ],
59 | ];
60 | }
61 |
62 | public function serializeDateTimeToJson(JsonSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
63 | {
64 | return $date->format($type['params'][0]);
65 | }
66 |
67 | public function deserializeDateTimeToJson(JsonDeserializationVisitor $visitor, $dateAsString, array $type, Context $context)
68 | {
69 | return new \DateTime($dateAsString);
70 | }
71 | }
72 |
73 | Also, this type of handler is registered via the builder object::
74 |
75 | $builder
76 | ->configureHandlers(function(JMS\Serializer\Handler\HandlerRegistry $registry) {
77 | $registry->registerSubscribingHandler(new MyHandler());
78 | })
79 | ;
80 |
81 | Skippable Subscribing Handlers
82 | -------------------------------
83 |
84 | In case you need to be able to fall back to the default deserialization behavior instead of using your custom
85 | handler, you can simply throw a `SkipHandlerException` from you custom handler method to do so.
86 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | Serializer
2 | ==========
3 |
4 | .. image:: logo-small.png
5 |
6 | Introduction
7 | ------------
8 | This library allows you to (de-)serialize data of any complexity. Currently, it supports XML and JSON.
9 |
10 | It also provides you with a rich tool-set to adapt the output to your specific needs.
11 |
12 | Built-in features include:
13 |
14 | - (De-)serialize data of any complexity; circular references are handled gracefully.
15 | - Supports many built-in PHP types (such as dates)
16 | - Integrates with Doctrine ORM, et. al.
17 | - Supports versioning, e.g. for APIs
18 | - Configurable via XML, YAML, or Doctrine Annotations
19 |
20 | Installation
21 | ------------
22 | This library can be easily installed via composer
23 |
24 | .. code-block :: bash
25 |
26 | composer require jms/serializer
27 |
28 | or just add it to your ``composer.json`` file directly.
29 |
30 | Usage
31 | -----
32 | For standalone projects usage of the provided builder is encouraged::
33 |
34 | $serializer = JMS\Serializer\SerializerBuilder::create()->build();
35 | $jsonContent = $serializer->serialize($data, 'json');
36 | echo $jsonContent; // or return it in a Response
37 |
38 |
39 | Documentation
40 | -------------
41 |
42 | .. toctree ::
43 | :maxdepth: 2
44 |
45 | configuration
46 | usage
47 | event_system
48 | handlers
49 | reference
50 | cookbook
51 |
52 | License
53 | -------
54 |
55 | The code is released under the business-friendly `MIT license`_.
56 |
57 | Documentation is subject to the `Attribution-NonCommercial-NoDerivs 3.0 Unported
58 | license`_.
59 |
60 | .. _MIT license: https://opensource.org/licenses/MIT
61 | .. _Attribution-NonCommercial-NoDerivs 3.0 Unported license: http://creativecommons.org/licenses/by-nc-nd/3.0/
62 |
63 |
--------------------------------------------------------------------------------
/doc/logo-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/schmittjoh/serializer/410da8bd35d727a9a62e85a3d9698102b145ea36/doc/logo-small.png
--------------------------------------------------------------------------------
/doc/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/schmittjoh/serializer/410da8bd35d727a9a62e85a3d9698102b145ea36/doc/logo.png
--------------------------------------------------------------------------------
/doc/reference.rst:
--------------------------------------------------------------------------------
1 | Reference
2 | =========
3 |
4 | .. toctree ::
5 | :glob:
6 | :maxdepth: 1
7 |
8 | reference/*
--------------------------------------------------------------------------------
/doc/reference/yml_reference.rst:
--------------------------------------------------------------------------------
1 | YAML Reference
2 | --------------
3 |
4 | .. code-block :: yaml
5 |
6 | # Vendor\MyBundle\Resources\config\serializer\Model.ClassName.yml
7 | Vendor\MyBundle\Model\ClassName:
8 | exclusion_policy: ALL
9 | xml_root_name: foobar
10 | xml_root_namespace: http://your.default.namespace
11 | exclude: true
12 | exclude_if: expr
13 | read_only: false
14 | access_type: public_method # defaults to property
15 | accessor_order: custom
16 | custom_accessor_order: [propertyName1, propertyName2, ..., propertyNameN]
17 | discriminator:
18 | field_name: type
19 | disabled: false
20 | map:
21 | some-value: ClassName
22 | groups: [foo, bar]
23 | xml_attribute: true
24 | xml_element:
25 | cdata: false
26 | namespace: http://www.w3.org/2005/Atom
27 | virtual_properties:
28 | getSomeProperty:
29 | name: optional-prop-name
30 | serialized_name: foo
31 | type: integer
32 | expression_prop:
33 | name: optional-prop-name
34 | exp: object.getName()
35 | serialized_name: foo
36 | type: integer
37 | xml_namespaces:
38 | "": http://your.default.namespace
39 | atom: http://www.w3.org/2005/Atom
40 | properties:
41 | some-property:
42 | exclude: true
43 | expose: true
44 | exclude_if: expr
45 | expose_if: expr
46 | skip_when_empty: false
47 | access_type: public_method # defaults to property
48 | accessor: # access_type must be set to public_method
49 | getter: getSomeOtherProperty
50 | setter: setSomeOtherProperty
51 | type: string
52 | serialized_name: foo
53 | since_version: 1.0
54 | until_version: 1.1
55 | groups: [foo, bar]
56 | xml_attribute: true
57 | xml_value: true
58 | inline: true
59 | read_only: true
60 | xml_key_value_pairs: true
61 | xml_list:
62 | inline: true
63 | entry_name: foo
64 | namespace: http://www.w3.org/2005/Atom
65 | xml_map:
66 | inline: true
67 | key_attribute_name: foo
68 | entry_name: bar
69 | namespace: http://www.w3.org/2005/Atom
70 | xml_attribute_map: true
71 | xml_element:
72 | cdata: false
73 | namespace: http://www.w3.org/2005/Atom
74 | max_depth: 2
75 | union_discriminator:
76 | filed: foo
77 | map:
78 | a: SomeClassFQCN1
79 | b: SomeClassFQCN2
80 | c: SomeClassFQCN3
81 |
82 | callback_methods:
83 | pre_serialize: [foo, bar]
84 | post_serialize: [foo, bar]
85 | post_deserialize: [foo, bar]
86 |
87 | Constants
88 | ---------
89 |
90 | In some cases, it may be helpful to reference constants in your YAML files.
91 | You can do this by prefixing the constant with the special `!php/const` syntax.
92 |
93 | .. code-block :: yaml
94 |
95 | Vendor\MyBundle\Model\ClassName:
96 | properties:
97 | some-property:
98 | serialized_name: !php/const Vendor\MyBundle\Model\ClassName::SOME_CONSTANT
99 |
--------------------------------------------------------------------------------
/doc/requirements.txt:
--------------------------------------------------------------------------------
1 | Sphinx==1.8.5
2 | git+https://github.com/fabpot/sphinx-php.git
3 | sphinx_rtd_theme
4 | Jinja2<3.0
5 | MarkupSafe<2.1
6 | alabaster<0.7.14
7 |
--------------------------------------------------------------------------------
/doc/usage.rst:
--------------------------------------------------------------------------------
1 | Usage
2 | =====
3 |
4 | Serializing Objects
5 | -------------------
6 | Most common usage is probably to serialize objects. This can be achieved
7 | very easily:
8 |
9 | .. configuration-block ::
10 |
11 | .. code-block :: php
12 |
13 | build();
16 | $serializer->serialize($object, 'json');
17 | $serializer->serialize($object, 'xml');
18 |
19 | .. code-block :: jinja
20 |
21 | {{ object | serialize }} {# uses JSON #}
22 | {{ object | serialize('json') }}
23 | {{ object | serialize('xml') }}
24 |
25 | Deserializing Objects
26 | ---------------------
27 | You can also deserialize objects from their XML, or JSON representation. For
28 | example, when accepting data via an API.
29 |
30 | .. code-block :: php
31 |
32 | build();
35 | $object = $serializer->deserialize($jsonData, \MyNamespace\MyObject::class, 'json');
36 |
37 |
--------------------------------------------------------------------------------
/phpbench.json:
--------------------------------------------------------------------------------
1 | {
2 | "runner.bootstrap": "tests/bootstrap.php",
3 | "runner.iterations": 3,
4 | "runner.revs": 1,
5 | "report.generators": {
6 | "memory": {
7 | "extends": "aggregate",
8 | "cols": [
9 | "benchmark",
10 | "mem_peak"
11 | ]
12 | }
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/phpstan.neon.dist:
--------------------------------------------------------------------------------
1 | includes:
2 | - phpstan/ignore-by-php-version.neon.php
3 | parameters:
4 | level: 3
5 | ignoreErrors:
6 | - '~Class Doctrine\\Common\\Persistence\\Proxy not found~'
7 | - '~Class Doctrine\\ODM\\MongoDB\\PersistentCollection not found~'
8 | - '~Class Symfony\\(Contracts|Component)\\Translation\\TranslatorInterface not found~'
9 | - '#Class JMS\\Serializer\\Annotation\\DeprecatedReadOnly extends @final class JMS\\Serializer\\Annotation\\ReadOnlyProperty.#'
10 | - '#^Call to an undefined method Doctrine\\Persistence\\Mapping\\ClassMetadata\