205f2e7f68bd — Carsten Grohmann 7 months ago
Extend documentation
2 files changed, 192 insertions(+), 26 deletions(-)

M JsonDottedReadAccess.py
M README.md
M JsonDottedReadAccess.py +8 -0
@@ 44,6 44,14 @@ class JsonDottedReadAccess(UserDict):
     'level3-d'
     >>> j.get('level1.level2-b')
     [{'level3-b': 1}]
+    >>> j.get('level1.nonexisting')
+    None
+    >>> j['level1.nonexisting']
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+      File "JsonDottedReadAccess.py", line 58, in __getitem__
+        val = val[key]
+    KeyError: 'nonexisting'
     """
 
     def __getitem__(self, key):

          
M README.md +184 -26
@@ 3,7 3,17 @@ Json Dotted Read Access
 
 [![builds.sr.ht status](https://builds.sr.ht/~carstengrohmann/JsonDottedReadAccess.svg)](https://builds.sr.ht/~carstengrohmann/JsonDottedReadAccess)
 
-Simplify deep access to JSON structures by introduce a dotted access notation. 
+Simplify access to JSON structures by introduce a dotted access notation.
+
+The intended use case is to read JSON data once. The use is not limited to
+JSON data. All data in a top level dictionary can be accessed. Use
+dictionaries and lists to structure these data. The data - the leafs in this
+data tree - can be all kind of Python objects.
+
+## Limitations
+ * no dots (.) in keys allowed
+ * read-only structure - no modifications (update/refresh) possible 
+ * no caching implemented
 
 ## Supported and tested Python versions
  * Python 2.7, tested with 2.7.17

          
@@ 13,26 23,169 @@ Simplify deep access to JSON structures 
 There are no additional requirements. All you need is Python.
 
 ## Installation
-Add the file `JsonDottedReadAccess.py` to your project and activate it like described in the "Usage" section.
+No installation is necessary. Just add the file `JsonDottedReadAccess.py` to
+your project and use it.
 
 ## Usage
+### Convert JSON string to a Python object
+
+This step is optional. You can use a Python object directly.
+
 ```python
->>> from JsonDottedReadAccess import JsonDottedReadAccess
->>> d = {u'level1': {u'level2-a': None,
-...                  u'level2-b': [{'level3-b': 1}],
-...                  u'level2-c': {'level3-c': 1},
-...                  u'level2-d': 'level3-d'}}
->>> j = JsonDottedReadAccess(d)
->>> j.get('level1')
-{u'level2-c': {'level3-c': 1}, u'level2-b': [{'level3-b': 1}], u'level2-a': None, u'level2-d': 'level3-d'}
->>> j.get('level1.level2-d')
-'level3-d'
->>> j.get('level1.level2-b')
-[{'level3-b': 1}]
+import json
+districts = """
+{
+    "cities":{
+        "Dresden":[
+            "Altstadt",
+            "Blasewitz",
+            "Cotta",
+            "Klotzsche",
+            "Leuben", 
+            "..."
+        ],
+        "Chemnitz":[
+            "Adelsberg",
+            "Altchemnitz",
+            "Altendorf",
+            "Bernsdorf",
+            "Borna-Heinersdorf",
+            "..."
+        ]
+    }
+}
+"""
+
+pyobj = json.loads(districts.strip())
+```
+
+### Create object for dotted access
+```python
+from JsonDottedReadAccess import JsonDottedReadAccess
+j = JsonDottedReadAccess(pyobj)
+```
+
+### Access methods
+#### `get(self, key, failobj=None)`
+`get(key)` returns fallback object, if the item doesn't exist.
+
+#### `__getitem__(self, key)`
+`[key]` raises `KeyError` or `IndexError` exceptions during access to
+non-existing items.
+
+### Access elements
+The individual elements are accessed via the description of the path, whereby
+the successive levels are connected by dots (".").
+
+Dictionary elements are accessed via keys and list elements via the numerical
+index.
+
+Access pattern:
+```python
+cities = j.get("cities")
+cities = j["cities"]
+
+non_existing_city = j.get("cities.non-existing", 42)
+
+destricts = j.get("cities.Dresden")
+destrict = j["cities.Dresden.2"]
+non_existing_destrict = j.get("cities.Dresden.non-existing", 42)
 ```
 
-## Project repository
-* [Mercurial Repository](https://hg.sr.ht/~carstengrohmann/JsonDottedReadAccess)
+More examples are shown on the section "Examples"
+
+## Examples
+### Basic Example: Access JSON data
+```python
+import json
+from JsonDottedReadAccess import JsonDottedReadAccess
+
+districts = """
+{
+    "cities":{
+        "Dresden":[
+            "Altstadt",
+            "Blasewitz",
+            "Cotta",
+            "Klotzsche",
+            "Leuben",
+            "..."
+        ],
+        "Chemnitz":[
+            "Adelsberg",
+            "Altchemnitz",
+            "Altendorf",
+            "Bernsdorf",
+            "Borna-Heinersdorf",
+            "..."
+        ]
+    }
+}
+"""
+
+pyobj = json.loads(districts.strip())
+j = JsonDottedReadAccess(pyobj)
+
+print(j.get("cities"))
+{u'Dresden': [u'Altstadt', u'Blasewitz', u'Cotta', u'Klotzsche', u'Leuben', u'...'], u'Chemnitz': [u'Adelsberg', u'Altchemnitz', u'Altendorf', u'Bernsdorf', u'Borna-Heinersdorf', u'...']}
+
+print( j.get("cities.Dresden"))
+[u'Altstadt', u'Blasewitz', u'Cotta', u'Klotzsche', u'Leuben', u'...']
+
+print(j.get("cities.Dresden.3"))
+Klotzsche
+```
+
+### Complex Example
+```python
+from JsonDottedReadAccess import JsonDottedReadAccess
+
+d = {'level1': {'level2-a': None,
+                'level2-b': [{'level3-b': 1}],
+                'level2-c': {'level3-c': 1},
+                'level2-d': 'level3-d'}}
+j = JsonDottedReadAccess(d)
+
+print(j.get('level1'))
+{'level2-c': {'level3-c': 1}, 'level2-b': [{'level3-b': 1}], 'level2-a': None, 'level2-d': 'level3-d'}
+
+print(j['level1.level2-b'])
+[{'level3-b': 1}]
+
+print(j.get('level1.level2-d'))
+'level3-d'
+
+print(j.get('level1.nonexisting'))
+None
+
+print(j['level1.nonexisting'])
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+  File "JsonDottedReadAccess.py", line 58, in __getitem__
+    val = val[key]
+KeyError: 'nonexisting'
+```
+
+## Changelog
+
+### March 2020
+ * Extend documentation
+
+### January 2020
+ * Extend tests
+ * get() catches IndexError and returns failobj instead
+ * Add Python3 compatibility
+
+### November 2017
+ * Initial version
+
+## Project page and feedback
+The project page is at <https://www.carstengrohmann.de/jsondottedreadaccess.html>.
+
+The source code is hosted at <https://hg.sr.ht/~carstengrohmann/JsonDottedReadAccess>.
+
+Comments, suggestions and patches are welcome and appreciated. Please send me
+an email.
 
 ## License
 

          
@@ 40,15 193,20 @@ This software is covered by the MIT Lice
 
 Copyright (c) 2017-2020 Carsten Grohmann <mail@carsten-grohmann.de>
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
-documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
-persons to whom the Software is furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
-Software.
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.