Re: [RFC][Discussion] Add #[NoSerialize] attribute for excluding properties or classes from serialization

From: Date: Tue, 28 Oct 2025 15:43:54 +0000
Subject: Re: [RFC][Discussion] Add #[NoSerialize] attribute for excluding properties or classes from serialization
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-128990@lists.php.net to get a copy of this message
Hi Dmytro On Tue, Oct 28, 2025 at 12:00 AM Dmytro Kulyk <lnkvisitor.ts@gmail.com> wrote: > > I’d like to open a discussion about a new proposal introducing the > #[NoSerialize] attribute, which allows developers to explicitly > exclude properties — or even entire classes — from native PHP > serialization. > > RFC: https://wiki.php.net/rfc/no_serialize_attribute > Implementation: https://github.com/php/php-src/pull/20074 Thank you for your proposal. I have a few comments. > When applied to a class, instances will be serialized as NULL. I don't understand the rationale for diverging from the existing @not-serializable behavior of internal classes, which throw when attempted to be serialized (e.g. Random\Engine\Secure). I see there's also a separate RFC to introduce that behavior: https://wiki.php.net/rfc/not_serializable_attribute I don't think there's a need for both of these attributes. To demonstrate, how would we even decide whether an internal class like PDO should get the #[NoSerialize] or #[NotSerializable] attribute? Informing the user of potentially incorrect serialization is the prudent option, and if they would like to skip the serialization of a property containing a PDO object they can simply mark it as #[NoSerialize]. The RFC says: > This approach ensures that data structures containing such objects (for example, arrays, > collections, or parent objects) remain valid and can be safely unserialized without errors, while > clearly indicating that the value was intentionally omitted. But is replacing unserializable objects with NULL in nested arrays really the safe choice? In these cases, I feel like a custom serializer that consciously replaces the object is warranted. This might also cause problems for typed properties: #[NoSerialize] class PDO {} class Foo { /* Will be happily serialized as NULL, but can't be restored because the * property is not nullable. */ public PDO $connection; } To summarize, I'd prefer if #[NoSerialize] on classes would cause serialize() to throw, like we already do for @not-serializable. > Class-level #[NoSerialize] is inherited by child classes unless explicitly overridden. Can you clarify how this would work? How can you override this attribute by omission? #[NoSerialize] class Foo {} /* What do I add here to remove #[NoSerialize]? */ class Bar extends Foo {} > Out of scope: JSON (json_encode(), JsonSerializable) and var_export() remain unaffected. Any future attempt to exclude properties marked as #[NoSerialize] from json_encode() would be backwards incompatible after this RFC has been implemented. To avoid this BC break, json_encode() would need a separate attribute (e.g. #[NoJsonEncode]). That sounds reasonable, but should be spelled out in the RFC. > Invalid Targets & Compile-Time Diagnostics What's the rationale for warning for some, but erroring for others? Ilija

« previous php.internals (#128990) next »