Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
S

Serde

> 编程语言
Open source

Robust Serde (serialization/deserialization) library for PHP 8.

355 stars0 likes0 views
WebsiteGitHub

About

Robust Serde (serialization/deserialization) library for PHP 8.

Serde

[![Latest Version on Packagist][ico-version]][link-packagist] ![Software License][ico-license] [![Total Downloads][ico-downloads]][link-downloads]

Serde (pronounced "seer-dee") is a fast, flexible, powerful, and easy to use serialization and deserialization library for PHP that supports a number of standard formats. It draws inspiration from both Rust's Serde crate and Symfony Serializer, although it is not directly based on either.

At this time, Serde supports serializing PHP objects to and from PHP arrays, JSON, YAML, TOML, and CSV files. It also supports serializing to JSON or CSV via a stream. Further support is planned, but by design can also be extended by anyone.

Install

Via Composer

$ composer require crell/serde

Usage

Serde is designed to be both quick to start using and robust in more advanced cases. In its most basic form, you can do the following:

use Crell\Serde\SerdeCommon;

$serde = new SerdeCommon();

$object = new SomeClass();
// Populate $object somehow;

$jsonString = $serde->serialize($object, format: 'json');

$deserializedObject = $serde->deserialize($jsonString, from: 'json', to: SomeClass::class);

(The named arguments are optional, but recommended.)

Serde is highly configurable, but common cases are supported by just using the SerdeCommon class as provided. For most basic cases, that is all you need.

Key features

Supported formats

Serde can serialize to:

  • PHP arrays (array)
  • JSON (json)
  • Streaming JSON (json-stream)
  • YAML (yaml)
  • TOML (toml)
  • CSV (csv)
  • Streaming CSV (csv-stream)

Serde can deserialize from:

  • PHP arrays (array)
  • JSON (json)
  • YAML (yaml)
  • TOML (toml)
  • CSV (csv)

YAML support requires the Symfony/Yaml library.

TOML support requires the Vanodevium/Toml library.

XML support is in progress.

Robust object support

Serde automatically supports nested objects in properties of other objects, which will be handled recursively as long as there are no circular references.

Serde handles public, private, protected, and readonly properties, both reading and writing, with optional default values.

If you try to serialize or deserialize an object that implements PHP's __serialize() or __unserialize() hooks, those will be respected. (If you want to read/write from PHP's internal serialization format, just call serialize()/unserialize() directly.)

Serde also supports post-load callbacks that allow you to re-initialize derived information if necessary without storing it in the serialized format.

PHP objects can be mutated to and from a serialized format. Nested objects can be flattened or collected, classes with common interfaces can be mapped to the appropriate object, and array values can be imploded into a string for serialization and exploded back into an array when reading.

Configuration

Serde's behavior is driven almost entirely through attributes. Any class may be serialized from or deserialized to as-is with no additional configuration, but there is a great deal of configuration that may be opted-in to.

Attribute handling is provided by Crell/AttributeUtils. It is worth looking into as well.

The main attribute is the Crell\Serde\Attributes\Field attribute, which may be placed on any object property. (Static properties are ignored.) All of its arguments are optional, as is the Field itself. (That is, adding #[Field] with no arguments is the same as not specifying it at all.) The meaning of the available arguments is listed below.

Although not required, it is strongly recommended that you always use named arguments with attributes. The precise order of arguments is not guaranteed.

In the examples below, the Field is generally referenced directly. However, you may also import the namespace and then use namespaced versions of the attributes, like so:

use Crell\Serde\Attributes as Serde;

#[Serde\ClassSettings(includeFieldsByDefault: false)]
class Person
{
    #[Serde\Field(serializedName: 'callme')]
    protected string $name = 'Larry';
}

Which you do is mostly a matter of preference, although if you are mixing Serde attributes with attributes from other libraries then the namespaced approach is advisable.

There is also a ClassSettings attribute that may be placed on classes to be serialized. At this time it has four arguments:

  • includeFieldsByDefault, which defaults to true. If set to false, a property with no #[Field] attribute will be ignored. It is equivalent to setting exclude: true on all properties implicitly.
  • requireValues, which defaults to false. If set to true, then when deserializing any field that is not provided in the incoming data will result in an exception. This may also be turned on or off on a per-field level. (See requireValue below.) The class-level setting applies to any field that does not specify its behavior.
  • renameWith. If set, the specified renaming strategy will be used for all properties of the class, unless a property specifies its own. (See renameWith below.) The class-level setting applies to any field that does not specify its behavior.
  • omitNullFields, which defaults to false. If set to true, any property on the class that is null will be omitted when serializing. It has no effect on deserialization. This may also be turned on or off on a per-field level. (See omitIfNull below.)
  • scopes, which sets the scope of a given class definition attribute. See the section on Scopes below.

exclude (bool, default false)

If set to true, Serde will ignore the property entirely on both serializing and deserializing.

serializedName (string, default null)

If provided, this string will be used as the name of a property when serialized out to a format and when reading it back in. for example:

use Crell\Serde\Attributes\Field;

class Person
{
    #[Field(serializedName: 'callme')]
    protected string $name = 'Larry';
}

Round trips to/from:

{
    "callme": "Larry"
}

renameWith (RenamingStrategy, default null)

The renameWith key specifies a way to mangle the name of the property to produce a serializedName. The most common examples here would be case folding, say if serializing to a format that uses a different convention than PHP does.

The value of renameWith can be any object that implements the RenamingStrategy interface. The most common versions are already provided via the Cases enum and Prefix class, but you are free to provide your own.

The Cases enum implements RenamingStrategy and provides a series of instances (cases) for common renaming. For example:

use Crell\Serde\Attributes\Field;
use Crell\Serde\Renaming\Cases;

class Person
{
    #[Field(renameWith: Cases::snake_case)]
    public string $firstName = 'Larry';

    #[Field(renameWith: Cases::CamelCase)]
    public string $lastName = 'Garfield';
}

Serializes to/from:

{
    "first_name": "Larry",
    "LastName": "Garfield"
}

Available cases are:

  • Cases::UPPERCASE
  • Cases::lowercase
  • Cases::snake_case
  • Cases::kebab_case (renders with dashes, not underscores)
  • Cases::CamelCase
  • Cases::lowerCamelCase

The Prefix class attaches a prefix to values when serialized, but otherwise leaves the property name intact.

use Crell\Serde\Attributes\Field;
use Crell\Serde\Renaming\Prefix;

class MailConfig
{
    #[Field(renameWith: new Prefix('mail_')]
    protected string $host = 'smtp.example.com';

    #[Field(renameWith: new Prefix('mail_')]
    protected int $port = 25;

    #[Field(renameWith: new Prefix('mail_')]
    protected string $user = 'me';

    #[Field(renameWith: new Prefix('mail_')]
    protected string $password = 'sssh';
}

Serializes to/from:

{
    "mail_host": "smtp.example.com",
    "mail_port": 25,
    "mail_user": "me",
    "mail_password": "sssh"
}

If both serializedName and renameWith are specified, serializedName will be used and renameWith ignored.

alias (array, default [])

When deserializing (only), if the expected serialized name is not found in the incoming data, these additional property names will be examined to see if the value can be found. If so, the value will be read from that key in the incoming data. If not, it will behave the same as if the value was simply not found in the first place.

use Crell\Serde\Attributes\Field;

class Person
{
    #[Field(alias: ['layout', 'design'])]
    protected string $format = '';
}

All three of the following JSON strings would be read into an identical object:

{
    "format": "3-column-layout"
}
{
    "layout": "3-column-layout"
}
{
    "design": "3-column-layout"
}

This is mainly useful when an API key has changed, and legacy incoming data may still have an old key name.

omitIfNull (bool, default false)

This key only applies on serialization. If set to true, and the value of this property is null when an object is serialized, it will be omitted from the output entirely. If false, a null will be written to the output, however that looks for the particular format.

useDefault (bool, default true)

This key only applies on deserialization. If a property of a class is not found in the incoming data, and this property is true, then a default value will be assigned instead. If false, the value will be skipped entirely. Whether the deserialized object is now in an invalid state depends on the object.

The default value to use is derived from a number of different locations. The priority order of defaults is:

  1. The value provided by the default argument to the Field attribute.
  2. The default value provided by the code, as reported by Reflection.
  3. The default value of an identically named constructor argument, if any.

So for example, the following class:

use Crell\Serde\Attributes\Field;

class Person
{
    #[Field(default: 'Hidden')]
    public string $location;

    #[Field(useDefault: false)]
    public int $age;

    public function __construct(
        public string $name = 'Anonymous',
    ) {}
}

if deserialized from an empty source (such as {} in JSON), will result in an object with location set to Hidden, name set to Anonymous, and age still uninitialized.

default (mixed, default null)

This key only applies on deserialization. If specified, then if a value is missing in the incoming data being deserialized this value will be used instead, regardless of what the default in the source code itself is.

strict (bool, default true)

This key only applies on deserialization. If set to true, a type mismatch in the incoming data will be rejected and an exception thrown. If false, a deformatter will attempt to cast an incoming value according to PHP's normal casting rules. That means, for example, "1" is a valid value for an integer property if strict is false, but will throw an exception if set to true.

For sequence fields, strict set to true will reject a non-sequence value. (It must pass an array_is_list() check.) If strict is false, any array-ish value will be accepted but passed through array_values() to discard any keys and reindex it.

Additionally, in non-strict mode, numeric strings in the incoming array will be cast to ints or floats as appropriate in both sequence fields and dictionary fields. In strict mode, numeric strings will still be rejected.

The exact handling of this setting may vary slightly depending on the incoming format, as some formats handle their

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

PHPdeserializationjsonphpserialization

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言