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;
    }