def request_elements(
            self, credentials=None, url=None, method='GET', params=None,
            headers=None, body='', json_input=None, return_json=False
    ):
        """
        Creates request elements for accessing **protected resource of a
        user**. Required arguments are :data:`credentials` and :data:`url`. You
        can pass :data:`credentials`, :data:`url`, :data:`method`, and
        :data:`params` as a JSON object.

        :param credentials:
            The **user's** credentials (can be serialized).

        :param str url:
            The url of the protected resource.

        :param str method:
            The HTTP method of the request.

        :param dict params:
            Dictionary of request parameters.

        :param dict headers:
            Dictionary of request headers.

        :param str body:
            Body of ``POST``, ``PUT`` and ``PATCH`` requests.

        :param str json_input:
            you can pass :data:`credentials`, :data:`url`, :data:`method`,
            :data:`params` and :data:`headers` in a JSON object.
            Values from arguments will be used for missing properties.

            ::

                {
                    "credentials": "###",
                    "url": "https://example.com/api",
                    "method": "POST",
                    "params": {
                        "foo": "bar"
                    },
                    "headers": {
                        "baz": "bing",
                        "Authorization": "Bearer ###"
                    },
                    "body": "Foo bar baz bing."
                }

        :param bool return_json:
            if ``True`` the function returns a json object.

            ::

                {
                    "url": "https://example.com/api",
                    "method": "POST",
                    "params": {
                        "access_token": "###",
                        "foo": "bar"
                    },
                    "headers": {
                        "baz": "bing",
                        "Authorization": "Bearer ###"
                    },
                    "body": "Foo bar baz bing."
                }

        :returns:
            :class:`.RequestElements` or JSON string.

        """

        # Parse values from JSON
        if json_input:
            parsed_input = json.loads(json_input)

            credentials = parsed_input.get('credentials', credentials)
            url = parsed_input.get('url', url)
            method = parsed_input.get('method', method)
            params = parsed_input.get('params', params)
            headers = parsed_input.get('headers', headers)
            body = parsed_input.get('body', body)

        if not credentials and url:
            raise RequestElementsError(
                'To create request elements, you must provide credentials '
                'and URL either as keyword arguments or in the JSON object!')

        # Get the provider class
        credentials = Credentials.deserialize(self.config, credentials)
        ProviderClass = credentials.provider_class

        # Create request elements
        request_elements = ProviderClass.create_request_elements(
            ProviderClass.PROTECTED_RESOURCE_REQUEST_TYPE,
            credentials=credentials,
            url=url,
            method=method,
            params=params,
            headers=headers,
            body=body)

        if return_json:
            return request_elements.to_json()

        else:
            return request_elements