public function getUserList()
    {
        // Tell LazyJsonMapper to give us all of our internal data as an array.
        // NOTE: This creates a COPY of the array. It's not attached to the main
        // storage, which means that any changes we make to the new array aren't
        // going to affect the actual LazyJsonMapper object's own data. That
        // won't matter for pure getter-based objects like this one (which is
        // all you'll need in 99.9999999% of cases where you'll want to read
        // unpredictable data). So if the user serializes this LazyJsonMapper
        // object, or gets it "asJson()", etc, then they'd still be serializing
        // the original, untouched internal data, which is exactly what we are
        // retrieving here. So everything works out perfectly as long as we
        // don't have any setters! (But setters will be demonstrated later.)
        if ($this->_userList === null) {
            // Get a copy of the internal data as an array, and cache it.
            // NOTE: This only throws if there is unmappable data internally.
            $this->_userList = $this->asArray(); // Throws.
        }

        // Loop through the list of JSON properties and convert every "array"
        // value to a User object instead. That's because all of JSON's nested,
        // not-yet-converted "JSON object values" are associative sub-arrays.
        foreach ($this->_userList as &$value) {
            if (is_array($value)) {
                // NOTE: The User constructor can only throw if a custom _init()
                // fails or if its class property map can't be compiled.
                $value = new User($value); // Throws.
            }
        }

        // Now just return our key-value array. The inner array values have
        // been converted to User objects, which makes them easy to work with.
        return $this->_userList;
    }