jms/serializer: turning a Doctrine object graph into JSON and XML
Library for (de-)serializing data of any complexity (supports JSON, and XML)
At a glance
- What is it?
- jms/serializer walks a PHP object graph and writes JSON or XML from it, handling circular references, exclusion strategies and field versioning for APIs. The mapping is a thing you write and maintain yourself, and the README documents neither the installation nor the type list.
- Who is it for?
- jms/serializer earns its place in a PHP API whose payload is a real object graph rather than a flat row, and it costs more than it looks like in a small application. What it buys is what a hand-built array and json_encode cannot express: cycles written as references, exclusion policies, dated types, and field names held steady across API versions.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- schmittjoh/serializer2,343 ★ · +2
| Repository | 2026-10-14 | 2026-10-23 |
|---|---|---|
| schmittjoh/serializer | 2.3k | 2.3k |
2 Stars in the last 9 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Object graphs in, JSON or XML out
A PHP API rarely has a flat array waiting to be encoded. Doctrine entities point at one another: a customer holds a collection of orders, and every order points back at the customer it came from. jms/serializer is built around that shape. It walks the object graph instead of a database row, writes JSON or XML from what it finds, and rebuilds objects on the return trip. The teams it fits are PHP shops whose domain model and wire format have drifted apart, and whose clients need the two pinned together as the model moves.
Dates, intervals and the type handler layer
The library's own feature list names many built-in PHP types, dates and intervals among them. Neither crosses an HTTP boundary as itself under a plain encoder, so each needs a handler that fixes the wire shape in one direction and accepts it again in the other. Intervals are the awkward case, because a duration has several reasonable serializations and no default one. That list stops at the category name: the README does not enumerate which types are covered, so anyone carrying an exotic value object has to check the documentation site rather than assume coverage.
Three configuration syntaxes, and no install command
Mapping is configured in three syntaxes, XML, YAML, or Annotations. Two of them put the object-to-wire contract in a file that can be diffed and reviewed; the third puts it on the property itself, next to the code that uses it. Installation is where this README runs thin. There is no composer require line, no version constraint and no PHP version requirement anywhere in it. The route offered is the Packagist badge for the `jms/serializer` package and the documentation link at http://jmsyst.com/libs/serializer, and a `composer.json` at the repository root is the only signpost that Composer is involved at all.
How circular references survive a round trip
A cycle is what breaks a naive encoder: customer to orders to customer cannot be written as a tree, and expanding the link until the process runs out of memory is not a remedy. jms/serializer names circular references and complex exclusion strategies as handled features. Exclusion strategies are the quieter half, since a property that must never leave the server, or one that would turn a small payload into a large one, has to be held back without being cut out of the class it belongs to. Versioning is the other half, and on an API it decides whether old clients keep working after a field is renamed.
The alternative most teams already have is a hand-built array plus json_encode, or a class implementing JsonSerializable. That route needs no mapping file, no annotations and no exclusion configuration, and it runs into the problems above precisely because the encoder walks what it finds on the object and has nowhere to record that a cycle should be written as a reference.
Tests, linters and benchmarks at the repository root
The repository root says more about how this project is worked on than the README does. Next to `src/` and `tests/` sit `phpunit.xml.dist` for the test run, `phpstan.neon.dist` and `phpcs.xml.dist` for static analysis and coding standards, `phpbench.json` for benchmarks, and `rector.php` for automated refactoring, with `doc/` holding the manual and `CONTRIBUTING.md`, `META.md`, `UPGRADING.md` beside them.
Two absences in that layout deserve naming. No dependency lock file is committed, so an install resolves against whatever the constraints permit on the day it runs. And no CI configuration sits at the root, even though the README carries a GitHub Actions badge pointing at a CI workflow on the `master` branch.
The entries, one per line:
.gitattributes
.github/
.gitignore
.run/
CHANGELOG.md
CONTRIBUTING.md
LICENSE
META.md
README.md
UPGRADING.md
composer.json
doc/
phpbench.json
phpcs.xml.dist
phpstan.neon.dist
phpstan/
phpunit.xml.dist
rector.php
src/
tests/Nothing in that listing is decoration: `doc/` is where the manual lives and `tests/` is where behaviour gets pinned.
The 1.x and 2.x branches froze and their fix windows closed
The README is blunt about branch support. The code on the default branch is the 3.x version, `master` is the supported line, and 1.x and 2.x are not supported anymore. The two fix windows it then names are ordered oddly. Security issues were to be fixed until the 1st January 2020, while only critical bugs might receive fixes until the 1st September 2019. A critical bug is a subset of a security issue, so the narrower promise ought to be the longer one, and this text gives the opposite. Both dates are long gone, which leaves 3.x as the only branch taking work, and the last push was on 2026-09-04.
The first block of the README is not about the library
Open the README on the default branch and the first block has nothing to do with serialization. It is an appeal for Ukraine dated 24 February 2022, carrying a volunteer fund link, a refugee aid link and a warning about Russian disinformation, and it sits above the project name and the logo. Further down, two details survive a close read. The project homepage, http://jmsyst.com/libs/serializer, is the only plain HTTP link in a file where every other destination uses https. And the feature list offers XML, YAML, or Annotations as the configuration syntaxes, while the repository's own tools, `phpstan.neon.dist`, `rector.php` and `phpcs.xml.dist`, come from a later generation of PHP practice; attributes appear nowhere in the file.
Paid support is a mailbox, not a contract
Paid support takes a single line: write an email to `[email protected]`. No scope, no rate, no response time and no second vendor are named, so a company that needs a support agreement has nothing there to hold anyone to. The library ships under MIT, the permissive licence that puts no copyleft obligation on code linking it and no requirement to publish changes in the application that uses it. The upgrade question sits apart from both, and UPGRADING.md is the document where the move from the old branches to 3.x is set out, which makes it the first file to read before editing a mapping.
Editorial conclusion
jms/serializer earns its place in a PHP API whose payload is a real object graph rather than a flat row, and it costs more than it looks like in a small application. What it buys is what a hand-built array and json_encode cannot express: cycles written as references, exclusion policies, dated types, and field names held steady across API versions. Before adopting, read UPGRADING.md, then confirm on the documentation site that your mapping covers every class you serialize and every type you send. In a project built this way the risk sits in a mapping file nobody reviews, not in the encoder.
Frequently asked questions
How do I install jms/serializer in a PHP project?
The README gives no composer require line and no version constraint, and points instead to the Packagist page for the `jms/serializer` package and to the documentation at http://jmsyst.com/libs/serializer. A `composer.json` at the root of the repository is the only signpost to Composer inside the file.
Does jms/serializer output YAML, or only JSON and XML?
Only JSON and XML are named as data formats. YAML shows up in the feature list as a configuration syntax alongside XML and Annotations, which is a different job from the format handed to a client.
Which branches of schmittjoh/serializer still receive work?
The README states that 3.x on the `master` branch is the supported version and that 1.x and 2.x are not supported anymore, with no additional feature releases planned and security fixes given until the 1st January 2020. Those two branches exist for anyone still reading the older code.
Can jms/serializer handle a Doctrine entity that points back at itself?
Circular references and complex exclusion strategies are named as handled features, and integration with Doctrine ORM is listed beside them. No worked example appears in the README, so the documentation site is where the mechanics are set out.
Is paid support available for jms/serializer?
The README names one address, `[email protected]`, and nothing else: no scope, price or response time. Every other pointer in the file leads to the documentation site or to the documents in the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/schmittjoh-serializer)Star history chart for your README
[](https://hysenlabs.com/projects/schmittjoh-serializer)Was this useful?