def test_items(self): from jsonweb.py3k import items if major_version() == 3: self.assertEqual(type(items({})), type({}.items())) if major_version() == 2: self.assertEqual(type(items({})), type({}.iteritems()))
def __new__(mcs, cls_name, bases, cls_dict): cls_dict["_fields"] = [k for k, v in items(cls_dict) if hasattr(v, "_validate")] for base in bases: if hasattr(base, "_fields"): cls_dict["_fields"].extend(base._fields) return type.__new__(mcs, cls_name, bases, cls_dict)
def __new__(mcs, cls_name, bases, cls_dict): cls_dict["_fields"] = [ k for k, v in items(cls_dict) if hasattr(v, "_validate") ] for base in bases: if hasattr(base, "_fields"): cls_dict["_fields"].extend(base._fields) return type.__new__(mcs, cls_name, bases, cls_dict)
def _validate(self, obj): isinstance_or_raise(obj, dict) errors = _Errors({}) validated_obj = {} for k, v in items(obj): if not self._key_is_valid(k, errors): continue try: validated_obj[k] = get_validator(self.validator).validate(v) except ValidationError as e: errors.add_error(e, key=k, reason_code="invalid_dict_value") errors.raise_if_errors("Error validating dict.", reason_code=self.reason_code) return validated_obj
def object_hook(handlers=None, as_type=None, validate=True): """ Wrapper around :class:`ObjectHook`. Calling this function will configure an instance of :class:`ObjectHook` and return a callable suitable for passing to :func:`json.loads` as ``object_hook``. If you need to decode a JSON string that does not contain a ``__type__`` key and you know that the JSON represents a certain object or list of objects you can use ``as_type`` to specify it :: >>> json_str = '{"first_name": "bob", "last_name": "smith"}' >>> loader(json_str, as_type="Person") <Person object at 0x1007d7550> >>> # lists work too >>> json_str = '''[ ... {"first_name": "bob", "last_name": "smith"}, ... {"first_name": "jane", "last_name": "smith"} ... ]''' >>> loader(json_str, as_type="Person") [<Person object at 0x1007d7550>, <Person object at 0x1007d7434>] .. note:: Assumes every object WITHOUT a ``__type__`` kw is of the type specified by ``as_type`` . ``handlers`` is a dict with this format:: {"Person": {"cls": Person, "handler": person_decoder, "schema": PersonSchema)} If you do not wish to decorate your classes with :func:`from_object` you can specify the same parameters via the ``handlers`` keyword argument. Here is an example:: >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name = first_name ... self.last_name = last_name ... >>> def person_decoder(cls, obj): ... return cls(obj["first_name"], obj["last_name"]) >>> handlers = {"Person": {"cls": Person, "handler": person_decoder}} >>> person = loader(json_str, handlers=handlers) >>> # Or invoking the object_hook interface ourselves >>> person = json.loads(json_str, object_hook=object_hook(handlers)) .. note:: If you decorate a class with :func:`from_object` you can override the ``handler`` and ``schema`` values later. Here is an example of overriding a schema you defined with :func:`from_object` (some code is left out for brevity):: >>> from jsonweb import from_object >>> @from_object(schema=PersonSchema) >>> class Person(object): ... >>> # and later on in the code... >>> handlers = {"Person": {"schema": NewPersonSchema}} >>> person = loader(json_str, handlers=handlers) If you need to use ``as_type`` or ``handlers`` many times in your code you can forgo using :func:`loader` in favor of configuring a "custom" object hook callable. Here is an example :: >>> my_obj_hook = object_hook(handlers) >>> # this call uses custom handlers >>> person = json.loads(json_str, object_hook=my_obj_hook) >>> # and so does this one ... >>> another_person = json.loads(json_str, object_hook=my_obj_hook) """ if handlers: _object_handlers = _default_object_handlers.copy() for name, handler_dict in items(handlers): if name in _object_handlers: _object_handlers.update_handler(name, **handler_dict) else: _object_handlers.add_handler( handler_dict.pop('cls'), **handler_dict ) else: _object_handlers = _default_object_handlers decode = ObjectHook(_object_handlers, validate) def handler(obj): if as_type and "__type__" not in obj: obj["__type__"] = as_type return decode.decode_obj(obj) return handler
def __iter__(self): for name, handler_tuple in items(self.__handlers): yield name, handler_tuple
def object_hook(handlers=None, as_type=None, validate=True): """ Wrapper around :class:`ObjectHook`. Calling this function will configure an instance of :class:`ObjectHook` and return a callable suitable for passing to :func:`json.loads` as ``object_hook``. If you need to decode a JSON string that does not contain a ``__type__`` key and you know that the JSON represents a certain object or list of objects you can use ``as_type`` to specify it :: >>> json_str = '{"first_name": "bob", "last_name": "smith"}' >>> loader(json_str, as_type="Person") <Person object at 0x1007d7550> >>> # lists work too >>> json_str = '''[ ... {"first_name": "bob", "last_name": "smith"}, ... {"first_name": "jane", "last_name": "smith"} ... ]''' >>> loader(json_str, as_type="Person") [<Person object at 0x1007d7550>, <Person object at 0x1007d7434>] .. note:: Assumes every object WITHOUT a ``__type__`` kw is of the type specified by ``as_type`` . ``handlers`` is a dict with this format:: {"Person": {"cls": Person, "handler": person_decoder, "schema": PersonSchema)} If you do not wish to decorate your classes with :func:`from_object` you can specify the same parameters via the ``handlers`` keyword argument. Here is an example:: >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name = first_name ... self.last_name = last_name ... >>> def person_decoder(cls, obj): ... return cls(obj["first_name"], obj["last_name"]) >>> handlers = {"Person": {"cls": Person, "handler": person_decoder}} >>> person = loader(json_str, handlers=handlers) >>> # Or invoking the object_hook interface ourselves >>> person = json.loads(json_str, object_hook=object_hook(handlers)) .. note:: If you decorate a class with :func:`from_object` you can override the ``handler`` and ``schema`` values later. Here is an example of overriding a schema you defined with :func:`from_object` (some code is left out for brevity):: >>> from jsonweb import from_object >>> @from_object(schema=PersonSchema) >>> class Person(object): ... >>> # and later on in the code... >>> handlers = {"Person": {"schema": NewPersonSchema}} >>> person = loader(json_str, handlers=handlers) If you need to use ``as_type`` or ``handlers`` many times in your code you can forgo using :func:`loader` in favor of configuring a "custom" object hook callable. Here is an example :: >>> my_obj_hook = object_hook(handlers) >>> # this call uses custom handlers >>> person = json.loads(json_str, object_hook=my_obj_hook) >>> # and so does this one ... >>> another_person = json.loads(json_str, object_hook=my_obj_hook) """ if handlers: _object_handlers = _default_object_handlers.copy() for name, handler_dict in items(handlers): if name in _object_handlers: _object_handlers.update_handler(name, **handler_dict) else: _object_handlers.add_handler(handler_dict.pop('cls'), **handler_dict) else: _object_handlers = _default_object_handlers decode = ObjectHook(_object_handlers, validate) def handler(obj): if as_type and "__type__" not in obj: obj["__type__"] = as_type return decode.decode_obj(obj) return handler