final public function exportObjectDataCopy(
        $objectRepresentation = 'array')
    {
        if (!in_array($objectRepresentation, ['stdClass', 'array'], true)) {
            throw new LazyJsonMapperException(sprintf(
                'Invalid object representation type "%s". Must be either "stdClass" or "array".',
                $objectRepresentation
            ));
        }

        // Make a shallow copy (copy-on-write) so that we will avoid affecting
        // our actual internal object data during the parsing below. Otherwise
        // we would turn all of OUR internal, still-unconverted sub-object
        // arrays into real objects on our REAL instance, and permanently cause
        // our object instance's memory usage to go up after an export call.
        $copy = clone $this;

        // Perform a NON-RECURSIVE analysis of the copy's top-level (own)
        // properties. This will CONVERT all of their values to the proper type,
        // and perform further sub-object creation (convert sub-object arrays
        // into real objects), etc. It also ensures no illegal values exist.
        // NOTE: For performance, we DON'T want recursive analysis, since we'll
        // soon be asking any sub-objects to analyze themselves one-by-one too!
        $analysis = $copy->exportClassAnalysis(false); // Never throws.

        // Abort if there are any BAD definitions (conversion failure due to
        // mismatches between defined class map and the actual data).
        if (!empty($analysis->bad_definitions)) { // Ignore missing_definitions
            $problemSummaries = $analysis->generateNiceSummaries();

            throw new LazyJsonMapperException(sprintf(
                'Unable to convert data to %s: %s',
                $objectRepresentation,
                $problemSummaries['bad_definitions'] // Tells them exact error.
            ));
        }

        // Now recursively process every other sub-object within the copy's data
        // via exportObjectDataCopy(), thus forcing all nested sub-objects
        // (which are still DIRECT REFERENCES to OUR "$this" original versions
        // of the objects, since objects are always by reference) to copy and
        // validate/convert THEMSELVES and their data and then return it
        // within the type of container we need. For a perfect final result.
        // NOTE: We iterate by &$value reference, but that WON'T affect the
        // objects they point to. It's a reference to the "_objectData" entry.
        array_walk_recursive($copy->_objectData, function (&$value, $key) use ($objectRepresentation) {
            // Only process objects. Everything else is already perfect (either
            // converted to the target-type if mapped or is valid "mixed" data).
            if (is_object($value)) {
                // Verify that the object is an instance of LazyJsonMapper.
                // NOTE: It SHOULDN'T be able to be anything else, since the
                // object analysis above has already verified that any "mixed"
                // (non-LazyJsonMapper) properties only contain basic PHP types.
                // But this check is a cheap safeguard against FUTURE bugs.
                if (!$value instanceof self) {
                    throw new LazyJsonMapperException(sprintf(
                        'Unable to convert data to %s: Unexpected "%s" object in property/key "%s", but we expected an instance of a LazyJsonMapper object.',
                        $objectRepresentation,
                        Utilities::createStrictClassPath(get_class($value)),
                        $key
                    ));
                }

                // Now just ask the sub-object to give us a copy of ITS verified
                // + converted data wrapped in the desired container type.
                // NOTE: This will be resolved recursively as-necessary for all
                // objects in the entire data tree.
                $value = $value->exportObjectDataCopy($objectRepresentation); // Throws.
            }
        });

        // Convert the outer data-holder to the object-representation type.
        if ($objectRepresentation === 'stdClass') {
            // When they want a stdClass, we MUST create it ourselves and assign
            // all of the internal data key-value pairs on it, with string-keys.
            $outputContainer = new stdClass();
            foreach ($copy->_objectData as $k => $v) {
                $outputContainer->{(string) $k} = $v;
            }
        } else { // 'array'
            // For an array-representation, we'll simply steal the copy's array.
            $outputContainer = $copy->_objectData;
        }

        // Voila, we now have their desired container, with cleaned-up and fully
        // validated copies of all of our internal data. And we haven't affected
        // any of our real $this data at all. Clones rock!
        // NOTE: And since $copy goes out of scope now, there will be no other
        // references to any of the data inside the container. It is therefore
        // fully encapsulated, standalone data which is safe to manipulate.
        return $outputContainer;
    }