final public function serialize()
    {
        // Tell all of our LJM-properties to pack themselves as plain arrays.
        // NOTE: We don't do any value-conversion or validation of properties,
        // since that's not our job. The user wants to SERIALIZE our data, so
        // translation of array entries to "class-map types" doesn't matter.
        $objectData = $this->_objectData; // Copy-on-write.
        array_walk_recursive($objectData, function (&$value) {
            if (is_object($value) && $value instanceof self) {
                // This call will recursively detect and take care of nested
                // objects and return ALL of their data as plain sub-arrays.
                $value = $value->serialize($value); // Throws.
            }
        });

        // If this is not the root object of a nested hierarchy, return raw arr.
        // NOTE: This efficiently packs all inner, nested LazyJsonMapper objects
        // by ensuring that their data joins the main root-level array again.
        $args = func_get_args(); // Check secret argument.
        $isRootObject = !isset($args[0]) || $args[0] !== $this;
        if (!$isRootObject) {
            return $objectData; // Secret, undocumented array return value.
        }

        // This is the root object that was asked to serialize itself, so finish
        // the process by serializing the data and validating its success.
        $serialized = null;

        try {
            // NOTE: This will ALWAYS succeed if the JSON data array is pure.
            $serialized = serialize($objectData); // Throws.
        } catch (\Exception $e) { // IMPORTANT: Catch ANY exception!
            // This can literally ONLY happen if the user has given us (and now
            // wants to serialize) non-JSON data containing other objects that
            // attempt (and fail) serialization and throw an exception instead.
            throw new LazySerializationException(sprintf(
                'Unexpected exception encountered while serializing a sub-object. Error: %s',
                $e->getMessage()
            ));
        }

        if (!is_string($serialized)) {
            // Anything other than a string means that serialize() failed.
            // NOTE: This should NEVER be able to happen!
            throw new LazySerializationException(
                'The object data could not be serialized.'
            );
        }

        // The data is fine. Now just return the string.
        return $serialized;
    }
final public function serialize()
    {
        // Tell all of our LJM-properties to pack themselves as plain arrays.
        // NOTE: We don't do any value-conversion or validation of properties,
        // since that's not our job. The user wants to SERIALIZE our data, so
        // translation of array entries to "class-map types" doesn't matter.
        $objectData = $this->_objectData; // Copy-on-write.
        array_walk_recursive($objectData, function (&$value) {
            if (is_object($value) && $value instanceof self) {
                // This call will recursively detect and take care of nested
                // objects and return ALL of their data as plain sub-arrays.
                $value = $value->serialize($value); // Throws.
            }
        });

        // If this is not the root object of a nested hierarchy, return raw arr.
        // NOTE: This efficiently packs all inner, nested LazyJsonMapper objects
        // by ensuring that their data joins the main root-level array again.
        $args = func_get_args(); // Check secret argument.
        $isRootObject = !isset($args[0]) || $args[0] !== $this;
        if (!$isRootObject) {
            return $objectData; // Secret, undocumented array return value.
        }

        // This is the root object that was asked to serialize itself, so finish
        // the process by serializing the data and validating its success.
        $serialized = null;

        try {
            // NOTE: This will ALWAYS succeed if the JSON data array is pure.
            $serialized = serialize($objectData); // Throws.
        } catch (\Exception $e) { // IMPORTANT: Catch ANY exception!
            // This can literally ONLY happen if the user has given us (and now
            // wants to serialize) non-JSON data containing other objects that
            // attempt (and fail) serialization and throw an exception instead.
            throw new LazySerializationException(sprintf(
                'Unexpected exception encountered while serializing a sub-object. Error: %s',
                $e->getMessage()
            ));
        }

        if (!is_string($serialized)) {
            // Anything other than a string means that serialize() failed.
            // NOTE: This should NEVER be able to happen!
            throw new LazySerializationException(
                'The object data could not be serialized.'
            );
        }

        // The data is fine. Now just return the string.
        return $serialized;
    }
final public function serialize ( ) { // Tell all of our LJM-properties to pack themselves as plain arrays. // NOTE: We don't do any value-conversion or validation of properties, // since that's not our job. The user wants to SERIALIZE our data, so // translation of array entries to "class-map types" doesn't matter. $ objectData = $ this -> _objectData ; // Copy-on-write. array_walk_recursive ( $ objectData , function ( & $ value ) { if ( is_object ( $ value ) && $ value instanceof self ) { // This call will recursively detect and take care of nested // objects and return ALL of their data as plain sub-arrays. $ value = $ value -> serialize ( $ value ) ; // Throws. } } ) ; // If this is not the root object of a nested hierarchy, return raw arr. // NOTE: This efficiently packs all inner, nested LazyJsonMapper objects // by ensuring that their data joins the main root-level array again. $ args = func_get_args ( ) ; // Check secret argument. $ isRootObject = ! isset ( $ args [ 0 ] ) || $ args [ 0 ] !== $ this ; if ( ! $ isRootObject ) { return $ objectData ; // Secret, undocumented array return value. } // This is the root object that was asked to serialize itself, so finish // the process by serializing the data and validating its success. $ serialized = null ; try { // NOTE: This will ALWAYS succeed if the JSON data array is pure. $ serialized = serialize ( $ objectData ) ; // Throws. } catch ( \ Exception $ e ) { // IMPORTANT: Catch ANY exception! // This can literally ONLY happen if the user has given us (and now // wants to serialize) non-JSON data containing other objects that // attempt (and fail) serialization and throw an exception instead. throw new LazySerializationException ( sprintf ( 'Unexpected exception encountered while serializing a sub-object. Error: %s' , $ e -> getMessage ( ) ) ) ; } if ( ! is_string ( $ serialized ) ) { // Anything other than a string means that serialize() failed. // NOTE: This should NEVER be able to happen! throw new LazySerializationException ( 'The object data could not be serialized.' ) ; } // The data is fine. Now just return the string. return $ serialized ; }
Called during serialization of the object.

You are not supposed to call this directly. Instead, use PHP's global
`serialize()` call:

```php
$savedStr = serialize($obj);
```

This serializer is thin and efficient. It simply recursively packs all
nested, internal `LazyJsonMapper` objects as a single, plain data array,
which guarantees the lowest possible serialized data size and the fastest
possible unserialization later (since there will only be a SINGLE parent
object that needs to wake up, rather than a whole tree).

There is no data conversion/validation of properties (ie to make them
match their "class property map"), since serialization is intended to
quickly save the internal contents of an instance to let you restore it
later, regardless of what was in your internal data property storage.

Also note that only the internal JSON data is serialized. We will not
serialize any subclass `$properties`, since that would be a misuse of how
your `LazyJsonMapper` subclasses are supposed to be designed. If they
need custom properties, then you can handle those in `_init()` as usual.

Lastly, you should know that calling `serialize()` will not disrupt any
internal data of the current object instance that you're serializing.
You can therefore continue to work with the object afterwards, or even
`serialize()` the same instance multiple times.

@throws LazySerializationException If the internal data array cannot be
serialized. But this problem can
literally NEVER happen unless YOU have
intentionally put totally-invalid,
non-serializable sub-objects within
your data array AND those objects in
turn throw exceptions when trying to
`serialize()`. That's NEVER going to
happen with real `json_decode()` data;
so if you constructed our object with
real JSON data then you never have to
look for `serialize()` exceptions.

@return string The object's internal data as a string representation.
Note that serialization produces strings containing binary
data which cannot be handled as text. It is intended for
storage in binary format (ie a `BLOB` database field).
Called during serialization of the object .