summaryrefslogtreecommitdiffstats
path: root/Lib/json
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2022-08-23 21:22:00 (GMT)
committerGitHub <noreply@github.com>2022-08-23 21:22:00 (GMT)
commit1f0eafa844bf5a380603d55e8d4b42d8c2a3439d (patch)
tree7d0baf97bbdeb48afea0e1685ce49b17f3855d95 /Lib/json
parent054328f0dd3e9ee5a8a026dfcfa606baf7e9f052 (diff)
downloadcpython-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__.py52
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))