diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2022-08-23 21:22:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-23 21:22:00 (GMT) |
commit | 1f0eafa844bf5a380603d55e8d4b42d8c2a3439d (patch) | |
tree | 7d0baf97bbdeb48afea0e1685ce49b17f3855d95 /Lib/json | |
parent | 054328f0dd3e9ee5a8a026dfcfa606baf7e9f052 (diff) | |
download | cpython-1f0eafa844bf5a380603d55e8d4b42d8c2a3439d.zip cpython-1f0eafa844bf5a380603d55e8d4b42d8c2a3439d.tar.gz cpython-1f0eafa844bf5a380603d55e8d4b42d8c2a3439d.tar.bz2 |
GH-96145: Add AttrDict to JSON module for use with object_hook (#96146)
Diffstat (limited to 'Lib/json')
-rw-r--r-- | Lib/json/__init__.py | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index e4c21da..d775fb1 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -97,7 +97,7 @@ Using json.tool from the shell to validate and pretty-print:: """ __version__ = '2.0.9' __all__ = [ - 'dump', 'dumps', 'load', 'loads', + 'dump', 'dumps', 'load', 'loads', 'AttrDict', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', ] @@ -357,3 +357,53 @@ def loads(s, *, cls=None, object_hook=None, parse_float=None, if parse_constant is not None: kw['parse_constant'] = parse_constant return cls(**kw).decode(s) + +class AttrDict(dict): + """Dict like object that supports attribute style dotted access. + + This class is intended for use with the *object_hook* in json.loads(): + + >>> from json import loads, AttrDict + >>> json_string = '{"mercury": 88, "venus": 225, "earth": 365, "mars": 687}' + >>> orbital_period = loads(json_string, object_hook=AttrDict) + >>> orbital_period['earth'] # Dict style lookup + 365 + >>> orbital_period.earth # Attribute style lookup + 365 + >>> orbital_period.keys() # All dict methods are present + dict_keys(['mercury', 'venus', 'earth', 'mars']) + + Attribute style access only works for keys that are valid attribute names. + In contrast, dictionary style access works for all keys. + For example, ``d.two words`` contains a space and is not syntactically + valid Python, so ``d["two words"]`` should be used instead. + + If a key has the same name as dictionary method, then a dictionary + lookup finds the key and an attribute lookup finds the method: + + >>> d = AttrDict(items=50) + >>> d['items'] # Lookup the key + 50 + >>> d.items() # Call the method + dict_items([('items', 50)]) + + """ + __slots__ = () + + def __getattr__(self, attr): + try: + return self[attr] + except KeyError: + raise AttributeError(attr) from None + + def __setattr__(self, attr, value): + self[attr] = value + + def __delattr__(self, attr): + try: + del self[attr] + except KeyError: + raise AttributeError(attr) from None + + def __dir__(self): + return list(self) + dir(type(self)) |