Validates a given JSON payload according to the rules defiined for all
        the fields/keys in the sub-class.

        :param dict payload: deserialized JSON object.
        :param bool required: if every field/key is required and must be
                              present in the payload.
        :param bool strict: if :py:meth:`validate` should detect and report any
                            fields/keys that are present in the payload but not
                            defined in the sub-class.

        :returns: a tuple of two items. First item is a :class:`bool`
                  indicating if the payload was successfully validated and the
                  second item is ``None``. If the payload was not valid, then
                  then the second item is a :py:class:`dict` of errors.

def validate(self, payload, required=None, strict=None):
        '''
        Validates a given JSON payload according to the rules defiined for all
        the fields/keys in the sub-class.

        :param dict payload: deserialized JSON object.
        :param bool required: if every field/key is required and must be
                              present in the payload.
        :param bool strict: if :py:meth:`validate` should detect and report any
                            fields/keys that are present in the payload but not
                            defined in the sub-class.

        :returns: a tuple of two items. First item is a :class:`bool`
                  indicating if the payload was successfully validated and the
                  second item is ``None``. If the payload was not valid, then
                  then the second item is a :py:class:`dict` of errors.
        '''

        # replace datatypes.Function.func if not already replaced
        self._replace_string_args()

        required = required if required is not None else self.required
        strict = strict if strict is not None else self.strict

        errors = PayloadErrors()
        fields = copy.deepcopy(list(self._fields))

        for key, value in iteritems(payload):
            if key not in self._fields:
                if strict:
                    errors[key].append(self.strict_error)
            else:
                getattr(self, key).test(key, value, payload=payload,
                                        errors=errors[key])

                # Remove the key that has been checked
                fields.remove(key)

        for field in fields:
            rule = getattr(self, field)

            if rule.required is None:
                required = required
            else:
                required = rule.required

            if required:
                errors[field].append(self.required_error)
            elif isinstance(rule, Function):
                rule.test(field, payload.get(field, None),
                          payload=payload, errors=errors[field])

        return (False, errors.to_dict()) if errors.has_errors() else (True,
                                                                      None)