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

From: Date: Wed, 29 Oct 2025 22:23:05 +0000
Subject: Re: [RFC][Discussion] Add #[NoSerialize] attribute for excluding properties or classes from serialization
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-129003@lists.php.net to get a copy of this message
Thanks for the feedback. > Thank you for your RFC. It is really well-written and nicely explains > the various (edge) cases. I've only read through the > #[\NoSerialize] > one, since it is the topic of this RFC discussion. I agree with Ilija on > all points. > > Am 2025-10-29 15:35, schrieb Dmytro Kulyk: > > #[NoSerialize], on the other hand, would apply to wrappers, > > containers, or domain objects where serialization of the rest of the > > structure should continue even if one field or nested object cannot be > > meaningfully serialized. > > But even for wrappers you can't guarantee that the wrapper is stored in > a nullable property. When applying the attribute to a field, omitting > the field makes sense, since the author of the property is the same > person who is capable of adding the attribute and thus is in full > control. This is different for classes where the author of the class > doesn't know how and where the class is being used. I thus agree with > Ilija that this should throw to clearly indicate that the user of the > class is doing something incorrect and to not silently corrupt data. If > an author of a class needs more fine-grained control, they can either > add the attribute to individual properties themselves - or implement > __serialize(). > You are right, this behavior can be non-obvious and lead to unexpected results. > >> > 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 {} > > > > Class-level #[NoSerialize] is transparently inherited by child classes. > > There’s currently no way to override or cancel this behavior in > > descendants; the attribute remains effective throughout the > > inheritance chain. > > Indeed, however the “unless explicitly overridden” bit in the RFC text > implies that this is possible. > > > As an alternative, #[NotSerializable] could be extended to > > #[NotSerializable(bool $soft = false)], which would provide the same > > behavior while keeping it in a separate, more consistent attribute — > > avoiding the double semantics currently implied by #[NoSerialize]. > > I don't think that sub classes should be able to make a non-serializable > parent class serializable, since they clearly won't be able to correctly > restore the state of the parent class. In fact I would consider this an > improvement over the existing serialization hooks where the child class > can simply skip calling the parent's serializer and thus create a > situation that the parent class does not expect to occur. It already makes no sense because the class-level attribute will be excluded from the RFC, and I have no plan to add something like this to #[NotSerializable]. It may be added in a future RFC. > > Initially, the idea was to make all of these cases emit warnings, but > > I didn’t figure out how to implement that consistently within the > > attribute validators. > > At this point, I don’t see any practical reason to allow the attribute > > on unsupported targets, so all such cases will be changed to > > compile-time errors instead of warnings. > > Yes, every clear error that is detectable at compile-time should be a > hard error to make it easy for users to detect the mistake. > Best regards Dmytro Kulyk

« previous php.internals (#129003) next »