Crell / Serde

Robust Serde (serialization/deserialization) library for PHP 8.
Other
296 stars 14 forks source link

mixed fails to serialize objects #23

Open withinboredom opened 1 year ago

withinboredom commented 1 year ago

Detailed description

When an object contains a mixed property containing an object, the property fails to serialize in MixedExporter due to not being an array, int, float, bool, or string.

Context

It would be nice to serialize generic objects.

Workaround

The workaround is to call $serde->serialize(...) on the mixed property and then serialize the parent object.

Crell commented 1 year ago

The problem here is that we will never be able to deserialize an object to mixed, as there's no indication of what the type is. Serialization is possible, but you're really better off specifying a real type in PHP.

withinboredom commented 1 year ago

Deserialization isn't an issue (the type is identified correctly by the deserializer through ClassNameTypeMap and friends). However, serialization is failing here.

Use-case: basically a wrapper containing metadata around a (de)serializable domain object.

Crell commented 1 year ago

On a lark, try the master branch. I pushed some cleanup yesterday that may have made objects work by accident. I just didn't write tests for it yet to be sure. 😄

Crell commented 1 year ago

OK, tested it, and it won't work. The problem is the refactored approach sends the value to serialize back through the serializer, which means the same object goes through Serializer::serialize() twice. Which... trips the circular dependency detection. :-) I don't know how to resolve that at this point, so unless someone has an idea it likely won't make it into the 1.0 release this month.

withinboredom commented 1 year ago

If it is mixed, and an object, can't it get the type via get_debug_type() for serialization? https://3v4l.org/iahAR Then make a decision from there?

Crell commented 1 year ago

Yes, but there's a lot of prep-work involved in preparing an object for exporting. ObjectExporter is one of the more involved implementations. It's not reasonable to duplicate that logic in MixedExporter, and technically no exporter knows about another exporter explicitly, by design. If they did, that would introduce complicated dependencies within the exporters, which so far I've managed to avoid (AFAIK).

So what it does right now is use get_debug_type() to set the type and route back through the serializer, so whatever exporter is configured will catch it and work normally.

Which is what triggers the circular dependency detection.

withinboredom commented 1 year ago

Ah, I see. FWIW, my workaround of simply serializing the mixed object to an array and then serializing the wrapping object into whatever seems to work fine. It takes a bit of extra work, but if you're wrapping an object with an object, you're already in a position to do that.

So, maybe this just needs to be documented so that it isn't a surprise?