jsonobjectify 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from json import dumps
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class JsonObject:
|
|
5
|
+
"""Represent a JSON object as a Python object."""
|
|
6
|
+
def __init__(self, info):
|
|
7
|
+
self._info = info
|
|
8
|
+
|
|
9
|
+
def __getattr__(self, name):
|
|
10
|
+
"""Return a value from the underlying JSON data using dot notation."""
|
|
11
|
+
try:
|
|
12
|
+
return self._info[name]
|
|
13
|
+
except KeyError:
|
|
14
|
+
raise AttributeError(f"{type(self).__name__} has no attribute {name!r}") from None
|
|
15
|
+
|
|
16
|
+
def __setattr__(self, name, value):
|
|
17
|
+
"""Set an attribute (_info) or update the underlying JSON data."""
|
|
18
|
+
if name == "_info":
|
|
19
|
+
super().__setattr__(name, value)
|
|
20
|
+
else:
|
|
21
|
+
self._info[name] = value
|
|
22
|
+
|
|
23
|
+
def to_dict(self):
|
|
24
|
+
"""Convert a JsonObject to dictionary."""
|
|
25
|
+
out_dict = {}
|
|
26
|
+
for key, value in self._info.items():
|
|
27
|
+
if isinstance(value, JsonObject):
|
|
28
|
+
out_dict[key] = value.to_dict()
|
|
29
|
+
elif isinstance(value, list):
|
|
30
|
+
out_dict[key] = [
|
|
31
|
+
item.to_dict() if isinstance(item, JsonObject) else item
|
|
32
|
+
for item in value
|
|
33
|
+
]
|
|
34
|
+
else:
|
|
35
|
+
out_dict[key] = value
|
|
36
|
+
return out_dict
|
|
37
|
+
|
|
38
|
+
def to_json(self):
|
|
39
|
+
"""Convert JsonObject to a JSON string."""
|
|
40
|
+
return dumps(self.to_dict())
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from json import load, loads
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from .json_object import JsonObject
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class JsonPath:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
"""Initialize an empty JSON parser."""
|
|
9
|
+
self._root_json_object = None
|
|
10
|
+
|
|
11
|
+
def __getattr__(self, name):
|
|
12
|
+
"""Delegate attribute access to the json object."""
|
|
13
|
+
return getattr(self._root_json_object, name)
|
|
14
|
+
|
|
15
|
+
def __getitem__(self, index):
|
|
16
|
+
"""Return an item from the root JSON array."""
|
|
17
|
+
return self._root_json_object[index]
|
|
18
|
+
|
|
19
|
+
def __len__(self):
|
|
20
|
+
"""Return the length of root JSON array/object"""
|
|
21
|
+
if isinstance(self._root_json_object, JsonObject):
|
|
22
|
+
return len(self._root_json_object.to_dict())
|
|
23
|
+
return len(self._root_json_object)
|
|
24
|
+
|
|
25
|
+
def __setattr__(self, name, value):
|
|
26
|
+
if name == "_root_json_object":
|
|
27
|
+
super().__setattr__(name, value)
|
|
28
|
+
else:
|
|
29
|
+
setattr(self._root_json_object, name, value)
|
|
30
|
+
|
|
31
|
+
def __str__(self):
|
|
32
|
+
if isinstance(self._root_json_object, JsonObject):
|
|
33
|
+
return self._root_json_object.to_json()
|
|
34
|
+
return f"{self._root_json_object}"
|
|
35
|
+
|
|
36
|
+
def __repr__(self):
|
|
37
|
+
if isinstance(self._root_json_object, JsonObject):
|
|
38
|
+
return f"{type(self).__name__}({self._root_json_object.to_dict()})"
|
|
39
|
+
return f"{type(self).__name__}({self._root_json_object})"
|
|
40
|
+
|
|
41
|
+
def _wrap_dict(self, data):
|
|
42
|
+
"""Wrap a dictionary in a JsonObject."""
|
|
43
|
+
return JsonObject(data)
|
|
44
|
+
|
|
45
|
+
def _is_valid_json_key(self, key):
|
|
46
|
+
"""Check whether a JSON key can be used as a Python attribute."""
|
|
47
|
+
if key.isidentifier():
|
|
48
|
+
return True
|
|
49
|
+
else:
|
|
50
|
+
print(f"Skipping invalid JSON key {key!r}")
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
def _process_list(self, data: list):
|
|
54
|
+
"""Recursively process items in a list."""
|
|
55
|
+
return [self._process_object(item) for item in data]
|
|
56
|
+
|
|
57
|
+
def _process_dict(self, data: dict):
|
|
58
|
+
"""Recursively process values in a dictionary."""
|
|
59
|
+
_data = {
|
|
60
|
+
key: self._process_object(value)
|
|
61
|
+
for key, value in data.items()
|
|
62
|
+
if self._is_valid_json_key(key)
|
|
63
|
+
}
|
|
64
|
+
return self._wrap_dict(_data)
|
|
65
|
+
|
|
66
|
+
def _process_object(self, value):
|
|
67
|
+
"""Process a JSON object based on its Python type."""
|
|
68
|
+
if isinstance(value, dict):
|
|
69
|
+
return self._process_dict(value)
|
|
70
|
+
elif isinstance(value, list):
|
|
71
|
+
return self._process_list(value)
|
|
72
|
+
return value
|
|
73
|
+
|
|
74
|
+
def _build_root_object(self, py_object):
|
|
75
|
+
"""Build the root object from the deserialized JSON."""
|
|
76
|
+
return self._process_object(py_object)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def _from_py_object(cls, py_object):
|
|
80
|
+
obj = cls()
|
|
81
|
+
obj._root_json_object = obj._build_root_object(py_object)
|
|
82
|
+
return obj
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_json_string(cls, json_string):
|
|
86
|
+
"""Create a JsonPath instance from a JSON string."""
|
|
87
|
+
if not isinstance(json_string, str):
|
|
88
|
+
raise TypeError("json_string must be a string")
|
|
89
|
+
if not json_string.strip():
|
|
90
|
+
raise ValueError("JSON string cannot be empty")
|
|
91
|
+
return cls._from_py_object(loads(json_string))
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def from_json_file(cls, filename: str):
|
|
95
|
+
"""Create a JsonPath instance from a JSON file."""
|
|
96
|
+
path = Path(filename)
|
|
97
|
+
if not path.is_file():
|
|
98
|
+
raise FileNotFoundError(f"File not found {filename}")
|
|
99
|
+
with open(path, mode="r", encoding="utf-8") as json_file:
|
|
100
|
+
return cls._from_py_object(load(json_file))
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: jsonobjectify
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: A lightweight Python library for converting JSON data into Python objects, simplifying access to nested structures through intuitive dot notation.
|
|
5
|
+
Author: Sandeep Suryaprasad
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Project-URL: Homepage, https://github.com/sandeepsuryaprasad/jsonobjectify
|
|
8
|
+
Project-URL: Repository, https://github.com/sandeepsuryaprasad/jsonobjectify
|
|
9
|
+
Project-URL: Issues, https://github.com/sandeepsuryaprasad/jsonobjectify/issues
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# jsonobjectify
|
|
13
|
+
|
|
14
|
+
A lightweight Python library for converting JSON data into Python objects,
|
|
15
|
+
simplifying access to nested structures through intuitive dot notation.
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
Working with complex JSON data often involves repetitive dictionary lookups, especially
|
|
19
|
+
when accessing deeply nested structures. `jsonobjectify` simplifies this process by
|
|
20
|
+
converting JSON data into Python objects, allowing you to access JSON properties using
|
|
21
|
+
familiar attribute notation.
|
|
22
|
+
|
|
23
|
+
Instead of writing chained dictionary lookups, you can navigate nested JSON structures
|
|
24
|
+
using a clean, readable, object-oriented interface.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
* **Dot-notation access:** Access JSON properties using Python attributes.
|
|
29
|
+
* **Nested object support:** Navigate deeply nested JSON structures naturally.
|
|
30
|
+
* **List support:** Work with collections of JSON objects.
|
|
31
|
+
* **Dictionary conversion:** Convert mapped objects back into standard Python dictionaries.
|
|
32
|
+
* **JSON serialization:** Serialize objects back into JSON.
|
|
33
|
+
* **Simple API:** Keep your code readable when working with complex JSON responses.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install jsonobjectify
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
Consider the following JSON data representing an employee and their department:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
response = """{
|
|
47
|
+
"id": 1,
|
|
48
|
+
"name": "Michael Anderson",
|
|
49
|
+
"email": "michael.anderson@example.com",
|
|
50
|
+
"website": "www.example.dev",
|
|
51
|
+
"address": {
|
|
52
|
+
"city": "Austin",
|
|
53
|
+
"state": "TX",
|
|
54
|
+
"country": "United States",
|
|
55
|
+
"geo_location": {"lat": "30.2672", "lng": "-97.7431"}
|
|
56
|
+
},
|
|
57
|
+
"skills": [
|
|
58
|
+
{"name": "Python", "level": "Advanced"},
|
|
59
|
+
{"name": "C", "level": "Advanced"},
|
|
60
|
+
{"name": "C++", "level": "Intermediate"}
|
|
61
|
+
]
|
|
62
|
+
}"""
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
With `jsonobjectify`, you can access the data through object attributes rather than
|
|
66
|
+
repeated dictionary lookups.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from jsonobjectify import JsonPath
|
|
70
|
+
|
|
71
|
+
employee = JsonPath.from_json_string(response)
|
|
72
|
+
|
|
73
|
+
print(employee.name)
|
|
74
|
+
print(employee.address.city)
|
|
75
|
+
print(employee.skills[0].name)
|
|
76
|
+
print(employee.skills[1].level)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Output**
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
'Michael Anderson'
|
|
83
|
+
'Austin'
|
|
84
|
+
'Python'
|
|
85
|
+
'Advanced'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The example above illustrates the intended API. Adjust the import and construction methods
|
|
89
|
+
to match the implementation in your repository.
|
|
90
|
+
|
|
91
|
+
## Converting Objects Back to JSON
|
|
92
|
+
|
|
93
|
+
`jsonobjectify` is intended to support conversion back to standard Python dictionaries and
|
|
94
|
+
JSON strings, making it convenient to work with transformed data.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# Convert the object to a Python dictionary
|
|
98
|
+
data = employee.to_dict()
|
|
99
|
+
|
|
100
|
+
# Serialize the object to a JSON string
|
|
101
|
+
json_data = employee.to_json()
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Requirements
|
|
105
|
+
|
|
106
|
+
* Python 3.9 or later
|
|
107
|
+
|
|
108
|
+
## Contributing
|
|
109
|
+
|
|
110
|
+
Contributions, bug reports, and feature suggestions are welcome. Please open an issue to
|
|
111
|
+
discuss a proposed change before submitting a pull request.
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
This project is licensed under the MIT License. See the `LICENSE` file for details.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
jsonobjectify/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
jsonobjectify/json_object.py,sha256=t-tflGSwGG2zqDlK6Iv6f7IEFB78GPl5Zlx9aR3YReg,1311
|
|
3
|
+
jsonobjectify/json_path.py,sha256=tA1qsD7ZtySb1t50z1ZMEo6gh_cUSFKzh3q0MbWoc5I,3531
|
|
4
|
+
jsonobjectify-0.0.0.dist-info/WHEEL,sha256=xTCBFIZIIyRSxyowOv5Wqg_jFU6KsdIffuulBB09Ph8,80
|
|
5
|
+
jsonobjectify-0.0.0.dist-info/METADATA,sha256=KVCmFJMtnFQvXoG0F61CAKHp2h_qCdU8V-S8WoC5zvQ,3436
|
|
6
|
+
jsonobjectify-0.0.0.dist-info/RECORD,,
|