jsonavigator 1.0.2__tar.gz
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.
- jsonavigator-1.0.2/LICENSE +21 -0
- jsonavigator-1.0.2/PKG-INFO +215 -0
- jsonavigator-1.0.2/README.md +200 -0
- jsonavigator-1.0.2/jsonavigator.egg-info/PKG-INFO +215 -0
- jsonavigator-1.0.2/jsonavigator.egg-info/SOURCES.txt +15 -0
- jsonavigator-1.0.2/jsonavigator.egg-info/dependency_links.txt +1 -0
- jsonavigator-1.0.2/jsonavigator.egg-info/top_level.txt +2 -0
- jsonavigator-1.0.2/jsoninja/__init__.py +26 -0
- jsonavigator-1.0.2/jsoninja/core.py +66 -0
- jsonavigator-1.0.2/jsoninja/exceptions.py +22 -0
- jsonavigator-1.0.2/jsoninja/utils.py +63 -0
- jsonavigator-1.0.2/setup.cfg +4 -0
- jsonavigator-1.0.2/setup.py +23 -0
- jsonavigator-1.0.2/tests/__init__.py +0 -0
- jsonavigator-1.0.2/tests/conftest.py +7 -0
- jsonavigator-1.0.2/tests/test_core.py +20 -0
- jsonavigator-1.0.2/tests/test_utils.py +89 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nikhil kumar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: jsonavigator
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: A Python package for handling nested JSON structures.
|
|
5
|
+
Home-page: https://github.com/Nikhil-Singh-2503/JSONavigator
|
|
6
|
+
Author: Nikhil Singh
|
|
7
|
+
Author-email: nikhilraj7654@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description:
|
|
10
|
+
# JSONavigator
|
|
11
|
+
|
|
12
|
+
JSONavigator is a Python package designed to simplify working with nested JSON structures. It provides utilities for traversing, flattening, validating, and formatting JSON paths, making it easier to handle complex data structures.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## **Features**
|
|
16
|
+
- **Traverse Nested JSON**: Recursively traverse dictionaries and lists to extract paths and values.
|
|
17
|
+
- **Flatten JSON**: Convert nested JSON into a single-level dictionary for easier access.
|
|
18
|
+
- **Validate Paths**: Ensure that JSON paths are properly formatted and valid.
|
|
19
|
+
- **Format Paths**: Improve readability of JSON paths by replacing separators with more user-friendly formats.
|
|
20
|
+
- **Custom Exceptions**: Handle errors gracefully with custom exception classes.
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
You can install `JSONavigator` using `pip`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install JSONavigator
|
|
27
|
+
```
|
|
28
|
+
Alternatively, if you’re installing from source:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
32
|
+
cd JSONavigator
|
|
33
|
+
```
|
|
34
|
+
Create Virtual envirnoment:
|
|
35
|
+
```bash
|
|
36
|
+
python -m venv venv
|
|
37
|
+
source venv/bin/activate
|
|
38
|
+
```
|
|
39
|
+
Install the requirements:
|
|
40
|
+
```bash
|
|
41
|
+
pip install -r requirements.txt
|
|
42
|
+
```
|
|
43
|
+
## Usage/Examples
|
|
44
|
+
Here’s how you can use the various features of JSONavigator:
|
|
45
|
+
|
|
46
|
+
**1. Traverse Nested JSON**
|
|
47
|
+
|
|
48
|
+
Use the `traverse_json` function to recursively traverse a nested JSON structure and extract paths and values.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from jsoninja.core import traverse_json
|
|
52
|
+
|
|
53
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
54
|
+
|
|
55
|
+
for path, value in traverse_json(data):
|
|
56
|
+
print(f"Path: {path}, Value: {value}")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Output**
|
|
60
|
+
```
|
|
61
|
+
Path: a.b[0], Value: 1
|
|
62
|
+
Path: a.b[1], Value: 2
|
|
63
|
+
Path: a.c, Value: 3
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**2. Get Value at a Specific Path**
|
|
67
|
+
|
|
68
|
+
Use the `get_value_at_path` function to retrieve the value at a specific path in the JSON structure.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from jsoninja.core import get_value_at_path
|
|
72
|
+
|
|
73
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
74
|
+
value = get_value_at_path(data, "a.b[1]")
|
|
75
|
+
print(value) # Output: 2
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Output**
|
|
79
|
+
`2`
|
|
80
|
+
|
|
81
|
+
**3. Flatten JSON**
|
|
82
|
+
|
|
83
|
+
Use the `flatten_json` function to convert a nested JSON structure into a single-level dictionary.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from jsoninja.utils import flatten_json
|
|
87
|
+
|
|
88
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
89
|
+
flattened = flatten_json(data)
|
|
90
|
+
print(flattened)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Output**
|
|
94
|
+
```
|
|
95
|
+
{
|
|
96
|
+
"a.b[0]": 1,
|
|
97
|
+
"a.b[1]": 2,
|
|
98
|
+
"a.c": 3
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
**4. Validate JSON Paths**
|
|
102
|
+
|
|
103
|
+
Use the `validate_path` function to ensure that a JSON path is properly formatted.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from jsoninja.utils import validate_path
|
|
107
|
+
from jsoninja.exceptions import InvalidPathError
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
validate_path("a.b[1]")
|
|
111
|
+
except InvalidPathError as e:
|
|
112
|
+
print(f"Invalid path: {e}")
|
|
113
|
+
```
|
|
114
|
+
**Output**
|
|
115
|
+
```
|
|
116
|
+
True
|
|
117
|
+
```
|
|
118
|
+
**5. Format JSON Paths**
|
|
119
|
+
|
|
120
|
+
Use the `format_path` function to make JSON paths more readable.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from jsoninja.utils import format_path
|
|
124
|
+
|
|
125
|
+
formatted_path = format_path("a.b[1]")
|
|
126
|
+
print(formatted_path)
|
|
127
|
+
```
|
|
128
|
+
**Output**
|
|
129
|
+
```
|
|
130
|
+
a -> b[1]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## **NOTE**
|
|
134
|
+
|
|
135
|
+
You can add your own seperator to each of the functions by passing value to a named variable `seperator`
|
|
136
|
+
|
|
137
|
+
**Example**
|
|
138
|
+
|
|
139
|
+
Suppose if you want to use seperator with `traverse_json` function.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from jsoninja.core import traverse_json
|
|
143
|
+
|
|
144
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
145
|
+
|
|
146
|
+
for path, value in traverse_json(data, seperator=*):
|
|
147
|
+
print(f"Path: {path}, Value: {value}")
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Output**
|
|
151
|
+
```
|
|
152
|
+
Path: a*b[0], Value: 1
|
|
153
|
+
Path: a*b[1], Value: 2
|
|
154
|
+
Path: a*c, Value: 3
|
|
155
|
+
```
|
|
156
|
+
## Contributing
|
|
157
|
+
|
|
158
|
+
Contributions to JSONavigator are welcome! To contribute:
|
|
159
|
+
|
|
160
|
+
- Fork the repository on GitHub.
|
|
161
|
+
- Clone your fork locally:
|
|
162
|
+
```bash
|
|
163
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
164
|
+
```
|
|
165
|
+
- Create a new branch for your feature or bugfix:
|
|
166
|
+
```bash
|
|
167
|
+
git checkout -b feature-name
|
|
168
|
+
```
|
|
169
|
+
- Make your changes and write tests if applicable.
|
|
170
|
+
|
|
171
|
+
- Run the tests to ensure everything works:
|
|
172
|
+
```bash
|
|
173
|
+
pytest
|
|
174
|
+
```
|
|
175
|
+
- Commit your changes and push them to your fork:
|
|
176
|
+
```bash
|
|
177
|
+
git commit -m "Add feature or fix"
|
|
178
|
+
git push origin feature-name
|
|
179
|
+
```
|
|
180
|
+
- Open a pull request on the main repository.
|
|
181
|
+
|
|
182
|
+
## Running Tests
|
|
183
|
+
|
|
184
|
+
To run the test suite, use `pytest`:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pytest
|
|
188
|
+
```
|
|
189
|
+
For coverage reports, install `pytest-cov` and run:
|
|
190
|
+
```bash
|
|
191
|
+
pytest --cov=JSONavigator
|
|
192
|
+
```
|
|
193
|
+
## License
|
|
194
|
+
This project is licensed under the MIT License.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
## Contact
|
|
199
|
+
|
|
200
|
+
If you have any questions or need support, feel free to reach out:
|
|
201
|
+
|
|
202
|
+
- Email: nikhilraj7654@gmail.com
|
|
203
|
+
|
|
204
|
+
## Acknowledgements
|
|
205
|
+
|
|
206
|
+
- Inspired by the need to simplify working with nested JSON structures.
|
|
207
|
+
- Built with ❤️ using Python.
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
Platform: UNKNOWN
|
|
211
|
+
Classifier: Programming Language :: Python :: 3
|
|
212
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
213
|
+
Classifier: Operating System :: OS Independent
|
|
214
|
+
Requires-Python: >=3.8
|
|
215
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
|
|
2
|
+
# JSONavigator
|
|
3
|
+
|
|
4
|
+
JSONavigator is a Python package designed to simplify working with nested JSON structures. It provides utilities for traversing, flattening, validating, and formatting JSON paths, making it easier to handle complex data structures.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## **Features**
|
|
8
|
+
- **Traverse Nested JSON**: Recursively traverse dictionaries and lists to extract paths and values.
|
|
9
|
+
- **Flatten JSON**: Convert nested JSON into a single-level dictionary for easier access.
|
|
10
|
+
- **Validate Paths**: Ensure that JSON paths are properly formatted and valid.
|
|
11
|
+
- **Format Paths**: Improve readability of JSON paths by replacing separators with more user-friendly formats.
|
|
12
|
+
- **Custom Exceptions**: Handle errors gracefully with custom exception classes.
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You can install `JSONavigator` using `pip`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install JSONavigator
|
|
19
|
+
```
|
|
20
|
+
Alternatively, if you’re installing from source:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
24
|
+
cd JSONavigator
|
|
25
|
+
```
|
|
26
|
+
Create Virtual envirnoment:
|
|
27
|
+
```bash
|
|
28
|
+
python -m venv venv
|
|
29
|
+
source venv/bin/activate
|
|
30
|
+
```
|
|
31
|
+
Install the requirements:
|
|
32
|
+
```bash
|
|
33
|
+
pip install -r requirements.txt
|
|
34
|
+
```
|
|
35
|
+
## Usage/Examples
|
|
36
|
+
Here’s how you can use the various features of JSONavigator:
|
|
37
|
+
|
|
38
|
+
**1. Traverse Nested JSON**
|
|
39
|
+
|
|
40
|
+
Use the `traverse_json` function to recursively traverse a nested JSON structure and extract paths and values.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from jsoninja.core import traverse_json
|
|
44
|
+
|
|
45
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
46
|
+
|
|
47
|
+
for path, value in traverse_json(data):
|
|
48
|
+
print(f"Path: {path}, Value: {value}")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Output**
|
|
52
|
+
```
|
|
53
|
+
Path: a.b[0], Value: 1
|
|
54
|
+
Path: a.b[1], Value: 2
|
|
55
|
+
Path: a.c, Value: 3
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**2. Get Value at a Specific Path**
|
|
59
|
+
|
|
60
|
+
Use the `get_value_at_path` function to retrieve the value at a specific path in the JSON structure.
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from jsoninja.core import get_value_at_path
|
|
64
|
+
|
|
65
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
66
|
+
value = get_value_at_path(data, "a.b[1]")
|
|
67
|
+
print(value) # Output: 2
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Output**
|
|
71
|
+
`2`
|
|
72
|
+
|
|
73
|
+
**3. Flatten JSON**
|
|
74
|
+
|
|
75
|
+
Use the `flatten_json` function to convert a nested JSON structure into a single-level dictionary.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from jsoninja.utils import flatten_json
|
|
79
|
+
|
|
80
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
81
|
+
flattened = flatten_json(data)
|
|
82
|
+
print(flattened)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Output**
|
|
86
|
+
```
|
|
87
|
+
{
|
|
88
|
+
"a.b[0]": 1,
|
|
89
|
+
"a.b[1]": 2,
|
|
90
|
+
"a.c": 3
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
**4. Validate JSON Paths**
|
|
94
|
+
|
|
95
|
+
Use the `validate_path` function to ensure that a JSON path is properly formatted.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from jsoninja.utils import validate_path
|
|
99
|
+
from jsoninja.exceptions import InvalidPathError
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
validate_path("a.b[1]")
|
|
103
|
+
except InvalidPathError as e:
|
|
104
|
+
print(f"Invalid path: {e}")
|
|
105
|
+
```
|
|
106
|
+
**Output**
|
|
107
|
+
```
|
|
108
|
+
True
|
|
109
|
+
```
|
|
110
|
+
**5. Format JSON Paths**
|
|
111
|
+
|
|
112
|
+
Use the `format_path` function to make JSON paths more readable.
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from jsoninja.utils import format_path
|
|
116
|
+
|
|
117
|
+
formatted_path = format_path("a.b[1]")
|
|
118
|
+
print(formatted_path)
|
|
119
|
+
```
|
|
120
|
+
**Output**
|
|
121
|
+
```
|
|
122
|
+
a -> b[1]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## **NOTE**
|
|
126
|
+
|
|
127
|
+
You can add your own seperator to each of the functions by passing value to a named variable `seperator`
|
|
128
|
+
|
|
129
|
+
**Example**
|
|
130
|
+
|
|
131
|
+
Suppose if you want to use seperator with `traverse_json` function.
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from jsoninja.core import traverse_json
|
|
135
|
+
|
|
136
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
137
|
+
|
|
138
|
+
for path, value in traverse_json(data, seperator=*):
|
|
139
|
+
print(f"Path: {path}, Value: {value}")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Output**
|
|
143
|
+
```
|
|
144
|
+
Path: a*b[0], Value: 1
|
|
145
|
+
Path: a*b[1], Value: 2
|
|
146
|
+
Path: a*c, Value: 3
|
|
147
|
+
```
|
|
148
|
+
## Contributing
|
|
149
|
+
|
|
150
|
+
Contributions to JSONavigator are welcome! To contribute:
|
|
151
|
+
|
|
152
|
+
- Fork the repository on GitHub.
|
|
153
|
+
- Clone your fork locally:
|
|
154
|
+
```bash
|
|
155
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
156
|
+
```
|
|
157
|
+
- Create a new branch for your feature or bugfix:
|
|
158
|
+
```bash
|
|
159
|
+
git checkout -b feature-name
|
|
160
|
+
```
|
|
161
|
+
- Make your changes and write tests if applicable.
|
|
162
|
+
|
|
163
|
+
- Run the tests to ensure everything works:
|
|
164
|
+
```bash
|
|
165
|
+
pytest
|
|
166
|
+
```
|
|
167
|
+
- Commit your changes and push them to your fork:
|
|
168
|
+
```bash
|
|
169
|
+
git commit -m "Add feature or fix"
|
|
170
|
+
git push origin feature-name
|
|
171
|
+
```
|
|
172
|
+
- Open a pull request on the main repository.
|
|
173
|
+
|
|
174
|
+
## Running Tests
|
|
175
|
+
|
|
176
|
+
To run the test suite, use `pytest`:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pytest
|
|
180
|
+
```
|
|
181
|
+
For coverage reports, install `pytest-cov` and run:
|
|
182
|
+
```bash
|
|
183
|
+
pytest --cov=JSONavigator
|
|
184
|
+
```
|
|
185
|
+
## License
|
|
186
|
+
This project is licensed under the MIT License.
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
## Contact
|
|
191
|
+
|
|
192
|
+
If you have any questions or need support, feel free to reach out:
|
|
193
|
+
|
|
194
|
+
- Email: nikhilraj7654@gmail.com
|
|
195
|
+
|
|
196
|
+
## Acknowledgements
|
|
197
|
+
|
|
198
|
+
- Inspired by the need to simplify working with nested JSON structures.
|
|
199
|
+
- Built with ❤️ using Python.
|
|
200
|
+
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: jsonavigator
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: A Python package for handling nested JSON structures.
|
|
5
|
+
Home-page: https://github.com/Nikhil-Singh-2503/JSONavigator
|
|
6
|
+
Author: Nikhil Singh
|
|
7
|
+
Author-email: nikhilraj7654@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description:
|
|
10
|
+
# JSONavigator
|
|
11
|
+
|
|
12
|
+
JSONavigator is a Python package designed to simplify working with nested JSON structures. It provides utilities for traversing, flattening, validating, and formatting JSON paths, making it easier to handle complex data structures.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## **Features**
|
|
16
|
+
- **Traverse Nested JSON**: Recursively traverse dictionaries and lists to extract paths and values.
|
|
17
|
+
- **Flatten JSON**: Convert nested JSON into a single-level dictionary for easier access.
|
|
18
|
+
- **Validate Paths**: Ensure that JSON paths are properly formatted and valid.
|
|
19
|
+
- **Format Paths**: Improve readability of JSON paths by replacing separators with more user-friendly formats.
|
|
20
|
+
- **Custom Exceptions**: Handle errors gracefully with custom exception classes.
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
You can install `JSONavigator` using `pip`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install JSONavigator
|
|
27
|
+
```
|
|
28
|
+
Alternatively, if you’re installing from source:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
32
|
+
cd JSONavigator
|
|
33
|
+
```
|
|
34
|
+
Create Virtual envirnoment:
|
|
35
|
+
```bash
|
|
36
|
+
python -m venv venv
|
|
37
|
+
source venv/bin/activate
|
|
38
|
+
```
|
|
39
|
+
Install the requirements:
|
|
40
|
+
```bash
|
|
41
|
+
pip install -r requirements.txt
|
|
42
|
+
```
|
|
43
|
+
## Usage/Examples
|
|
44
|
+
Here’s how you can use the various features of JSONavigator:
|
|
45
|
+
|
|
46
|
+
**1. Traverse Nested JSON**
|
|
47
|
+
|
|
48
|
+
Use the `traverse_json` function to recursively traverse a nested JSON structure and extract paths and values.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from jsoninja.core import traverse_json
|
|
52
|
+
|
|
53
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
54
|
+
|
|
55
|
+
for path, value in traverse_json(data):
|
|
56
|
+
print(f"Path: {path}, Value: {value}")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Output**
|
|
60
|
+
```
|
|
61
|
+
Path: a.b[0], Value: 1
|
|
62
|
+
Path: a.b[1], Value: 2
|
|
63
|
+
Path: a.c, Value: 3
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**2. Get Value at a Specific Path**
|
|
67
|
+
|
|
68
|
+
Use the `get_value_at_path` function to retrieve the value at a specific path in the JSON structure.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from jsoninja.core import get_value_at_path
|
|
72
|
+
|
|
73
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
74
|
+
value = get_value_at_path(data, "a.b[1]")
|
|
75
|
+
print(value) # Output: 2
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Output**
|
|
79
|
+
`2`
|
|
80
|
+
|
|
81
|
+
**3. Flatten JSON**
|
|
82
|
+
|
|
83
|
+
Use the `flatten_json` function to convert a nested JSON structure into a single-level dictionary.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from jsoninja.utils import flatten_json
|
|
87
|
+
|
|
88
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
89
|
+
flattened = flatten_json(data)
|
|
90
|
+
print(flattened)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Output**
|
|
94
|
+
```
|
|
95
|
+
{
|
|
96
|
+
"a.b[0]": 1,
|
|
97
|
+
"a.b[1]": 2,
|
|
98
|
+
"a.c": 3
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
**4. Validate JSON Paths**
|
|
102
|
+
|
|
103
|
+
Use the `validate_path` function to ensure that a JSON path is properly formatted.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from jsoninja.utils import validate_path
|
|
107
|
+
from jsoninja.exceptions import InvalidPathError
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
validate_path("a.b[1]")
|
|
111
|
+
except InvalidPathError as e:
|
|
112
|
+
print(f"Invalid path: {e}")
|
|
113
|
+
```
|
|
114
|
+
**Output**
|
|
115
|
+
```
|
|
116
|
+
True
|
|
117
|
+
```
|
|
118
|
+
**5. Format JSON Paths**
|
|
119
|
+
|
|
120
|
+
Use the `format_path` function to make JSON paths more readable.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from jsoninja.utils import format_path
|
|
124
|
+
|
|
125
|
+
formatted_path = format_path("a.b[1]")
|
|
126
|
+
print(formatted_path)
|
|
127
|
+
```
|
|
128
|
+
**Output**
|
|
129
|
+
```
|
|
130
|
+
a -> b[1]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## **NOTE**
|
|
134
|
+
|
|
135
|
+
You can add your own seperator to each of the functions by passing value to a named variable `seperator`
|
|
136
|
+
|
|
137
|
+
**Example**
|
|
138
|
+
|
|
139
|
+
Suppose if you want to use seperator with `traverse_json` function.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from jsoninja.core import traverse_json
|
|
143
|
+
|
|
144
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
145
|
+
|
|
146
|
+
for path, value in traverse_json(data, seperator=*):
|
|
147
|
+
print(f"Path: {path}, Value: {value}")
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Output**
|
|
151
|
+
```
|
|
152
|
+
Path: a*b[0], Value: 1
|
|
153
|
+
Path: a*b[1], Value: 2
|
|
154
|
+
Path: a*c, Value: 3
|
|
155
|
+
```
|
|
156
|
+
## Contributing
|
|
157
|
+
|
|
158
|
+
Contributions to JSONavigator are welcome! To contribute:
|
|
159
|
+
|
|
160
|
+
- Fork the repository on GitHub.
|
|
161
|
+
- Clone your fork locally:
|
|
162
|
+
```bash
|
|
163
|
+
git clone https://github.com/Nikhil-Singh-2503/JSONavigator.git
|
|
164
|
+
```
|
|
165
|
+
- Create a new branch for your feature or bugfix:
|
|
166
|
+
```bash
|
|
167
|
+
git checkout -b feature-name
|
|
168
|
+
```
|
|
169
|
+
- Make your changes and write tests if applicable.
|
|
170
|
+
|
|
171
|
+
- Run the tests to ensure everything works:
|
|
172
|
+
```bash
|
|
173
|
+
pytest
|
|
174
|
+
```
|
|
175
|
+
- Commit your changes and push them to your fork:
|
|
176
|
+
```bash
|
|
177
|
+
git commit -m "Add feature or fix"
|
|
178
|
+
git push origin feature-name
|
|
179
|
+
```
|
|
180
|
+
- Open a pull request on the main repository.
|
|
181
|
+
|
|
182
|
+
## Running Tests
|
|
183
|
+
|
|
184
|
+
To run the test suite, use `pytest`:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pytest
|
|
188
|
+
```
|
|
189
|
+
For coverage reports, install `pytest-cov` and run:
|
|
190
|
+
```bash
|
|
191
|
+
pytest --cov=JSONavigator
|
|
192
|
+
```
|
|
193
|
+
## License
|
|
194
|
+
This project is licensed under the MIT License.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
## Contact
|
|
199
|
+
|
|
200
|
+
If you have any questions or need support, feel free to reach out:
|
|
201
|
+
|
|
202
|
+
- Email: nikhilraj7654@gmail.com
|
|
203
|
+
|
|
204
|
+
## Acknowledgements
|
|
205
|
+
|
|
206
|
+
- Inspired by the need to simplify working with nested JSON structures.
|
|
207
|
+
- Built with ❤️ using Python.
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
Platform: UNKNOWN
|
|
211
|
+
Classifier: Programming Language :: Python :: 3
|
|
212
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
213
|
+
Classifier: Operating System :: OS Independent
|
|
214
|
+
Requires-Python: >=3.8
|
|
215
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
jsonavigator.egg-info/PKG-INFO
|
|
5
|
+
jsonavigator.egg-info/SOURCES.txt
|
|
6
|
+
jsonavigator.egg-info/dependency_links.txt
|
|
7
|
+
jsonavigator.egg-info/top_level.txt
|
|
8
|
+
jsoninja/__init__.py
|
|
9
|
+
jsoninja/core.py
|
|
10
|
+
jsoninja/exceptions.py
|
|
11
|
+
jsoninja/utils.py
|
|
12
|
+
tests/__init__.py
|
|
13
|
+
tests/conftest.py
|
|
14
|
+
tests/test_core.py
|
|
15
|
+
tests/test_utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Import core functions from the core module
|
|
2
|
+
from jsoninja.core import (
|
|
3
|
+
traverse_json,
|
|
4
|
+
get_value_at_path,
|
|
5
|
+
find_all_paths_for_element
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
# Import custom exceptions from the exceptions module
|
|
9
|
+
from jsoninja.exceptions import (
|
|
10
|
+
InvalidPathError,
|
|
11
|
+
ElementNotFoundError
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Define what is exposed when someone uses `from nested_json_utils import *`
|
|
15
|
+
__all__ = [
|
|
16
|
+
"traverse_json",
|
|
17
|
+
"get_value_at_path",
|
|
18
|
+
"find_all_paths_for_element",
|
|
19
|
+
"InvalidPathError",
|
|
20
|
+
"ElementNotFoundError"
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
# Optionally, define package metadata
|
|
24
|
+
__version__ = "0.1.0"
|
|
25
|
+
__author__ = "Nikhil Singh"
|
|
26
|
+
__email__ = "nikhilraj7654@gmail.com"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import re
|
|
2
|
+
def traverse_json(data, parent_key='', separator='.'):
|
|
3
|
+
"""
|
|
4
|
+
Recursively traverse a nested JSON structure and yield paths and values.
|
|
5
|
+
:param data: The JSON data (dict or list).
|
|
6
|
+
:param parent_key: The accumulated key path.
|
|
7
|
+
:param separator: The separator to join keys.
|
|
8
|
+
:yield: (path, value) tuples.
|
|
9
|
+
"""
|
|
10
|
+
if isinstance(data, dict):
|
|
11
|
+
for key, value in data.items():
|
|
12
|
+
new_key = f"{parent_key}{separator}{key}" if parent_key else key
|
|
13
|
+
yield from traverse_json(value, new_key, separator)
|
|
14
|
+
elif isinstance(data, list):
|
|
15
|
+
for index, value in enumerate(data):
|
|
16
|
+
new_key = f"{parent_key}[{index}]"
|
|
17
|
+
yield from traverse_json(value, new_key, separator)
|
|
18
|
+
else:
|
|
19
|
+
yield parent_key, data
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_value_at_path(data, path, separator='.'):
|
|
23
|
+
"""
|
|
24
|
+
Get the value at a given path in the JSON structure.
|
|
25
|
+
:param data: The JSON data (dict or list).
|
|
26
|
+
:param path: The path to the desired element.
|
|
27
|
+
:param separator: The separator used in the path.
|
|
28
|
+
:return: The value at the given path.
|
|
29
|
+
"""
|
|
30
|
+
# Regular expression to match keys (e.g., "a") and indices (e.g., "[1]")
|
|
31
|
+
pattern = re.compile(rf'[^{re.escape(separator)}\[\]]+|\[\d+\]')
|
|
32
|
+
|
|
33
|
+
# Split the path into components
|
|
34
|
+
components = pattern.findall(path)
|
|
35
|
+
current = data
|
|
36
|
+
|
|
37
|
+
for component in components:
|
|
38
|
+
if component.startswith('[') and component.endswith(']'):
|
|
39
|
+
# Extract the index from the brackets
|
|
40
|
+
index = int(component[1:-1])
|
|
41
|
+
if isinstance(current, list):
|
|
42
|
+
current = current[index]
|
|
43
|
+
else:
|
|
44
|
+
raise KeyError(f"Index {index} accessed on non-list: {current}")
|
|
45
|
+
else:
|
|
46
|
+
# Access the key in the dictionary
|
|
47
|
+
if isinstance(current, dict):
|
|
48
|
+
current = current[component]
|
|
49
|
+
else:
|
|
50
|
+
raise KeyError(f"Key {component} accessed on non-dictionary: {current}")
|
|
51
|
+
|
|
52
|
+
return current
|
|
53
|
+
|
|
54
|
+
def find_all_paths_for_element(data, target, separator='.'):
|
|
55
|
+
"""
|
|
56
|
+
Find all paths where the target element exists.
|
|
57
|
+
:param data: The JSON data (dict or list).
|
|
58
|
+
:param target: The target element to search for.
|
|
59
|
+
:param separator: The separator used in paths.
|
|
60
|
+
:return: List of paths where the target element is found.
|
|
61
|
+
"""
|
|
62
|
+
paths = []
|
|
63
|
+
for path, value in traverse_json(data, separator=separator):
|
|
64
|
+
if value == target:
|
|
65
|
+
paths.append(path)
|
|
66
|
+
return paths
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class NestedJSONUtilsError(Exception):
|
|
2
|
+
"""Base class for all exceptions in the nested_json_utils package."""
|
|
3
|
+
pass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InvalidPathError(NestedJSONUtilsError):
|
|
7
|
+
"""Raised when an invalid path is provided."""
|
|
8
|
+
def __init__(self, message="Invalid path provided."):
|
|
9
|
+
super().__init__(message)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ElementNotFoundError(NestedJSONUtilsError):
|
|
13
|
+
"""Raised when the target element is not found in the JSON structure."""
|
|
14
|
+
def __init__(self, element, message="Element not found in JSON structure."):
|
|
15
|
+
self.element = element
|
|
16
|
+
super().__init__(f"{message} Element: {element}")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class JSONStructureError(NestedJSONUtilsError):
|
|
20
|
+
"""Raised when there is an issue with the JSON structure."""
|
|
21
|
+
def __init__(self, message="Invalid JSON structure."):
|
|
22
|
+
super().__init__(message)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from .exceptions import InvalidPathError
|
|
2
|
+
|
|
3
|
+
def validate_path(path, separator='.'):
|
|
4
|
+
"""
|
|
5
|
+
Validate if a given path is properly formatted.
|
|
6
|
+
:param path: The path to validate.
|
|
7
|
+
:param separator: The separator used in the path.
|
|
8
|
+
:raises InvalidPathError: If the path is invalid.
|
|
9
|
+
"""
|
|
10
|
+
check = True
|
|
11
|
+
if not isinstance(path, str):
|
|
12
|
+
raise InvalidPathError("Path must be a string.")
|
|
13
|
+
|
|
14
|
+
# Check if the path contains only valid characters
|
|
15
|
+
valid_chars = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[]_")
|
|
16
|
+
valid_chars.add(separator)
|
|
17
|
+
for char in path:
|
|
18
|
+
if char not in valid_chars:
|
|
19
|
+
check = False
|
|
20
|
+
raise InvalidPathError(f"Invalid character '{char}' in path.")
|
|
21
|
+
|
|
22
|
+
# Ensure brackets are properly closed if present
|
|
23
|
+
if '[' in path or ']' in path:
|
|
24
|
+
if path.count('[') != path.count(']'):
|
|
25
|
+
check = False
|
|
26
|
+
raise InvalidPathError("Mismatched brackets in path.")
|
|
27
|
+
return check
|
|
28
|
+
|
|
29
|
+
def format_path(path, separator='.'):
|
|
30
|
+
"""
|
|
31
|
+
Format a path for better readability.
|
|
32
|
+
:param path: The path to format.
|
|
33
|
+
:param separator: The separator used in the path.
|
|
34
|
+
:return: A formatted version of the path.
|
|
35
|
+
"""
|
|
36
|
+
if not isinstance(path, str):
|
|
37
|
+
raise InvalidPathError("Path must be a string.")
|
|
38
|
+
|
|
39
|
+
# Replace separators with a more readable format if needed
|
|
40
|
+
return path.replace(separator, " -> ")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def flatten_json(data, parent_key='', separator='.'):
|
|
44
|
+
"""
|
|
45
|
+
Flatten a nested JSON structure into a single-level dictionary.
|
|
46
|
+
:param data: The JSON data (dict or list).
|
|
47
|
+
:param parent_key: The accumulated key path.
|
|
48
|
+
:param separator: The separator to join keys.
|
|
49
|
+
:return: A flattened dictionary.
|
|
50
|
+
"""
|
|
51
|
+
items = {}
|
|
52
|
+
if isinstance(data, dict):
|
|
53
|
+
for key, value in data.items():
|
|
54
|
+
new_key = f"{parent_key}{separator}{key}" if parent_key else key
|
|
55
|
+
items.update(flatten_json(value, new_key, separator))
|
|
56
|
+
elif isinstance(data, list):
|
|
57
|
+
for index, value in enumerate(data):
|
|
58
|
+
new_key = f"{parent_key}[{index}]"
|
|
59
|
+
items.update(flatten_json(value, new_key, separator))
|
|
60
|
+
else:
|
|
61
|
+
items[parent_key] = data
|
|
62
|
+
return items
|
|
63
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
4
|
+
long_description = fh.read()
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name="jsonavigator",
|
|
8
|
+
version="1.0.2",
|
|
9
|
+
author="Nikhil Singh",
|
|
10
|
+
author_email="nikhilraj7654@gmail.com",
|
|
11
|
+
description="A Python package for handling nested JSON structures.",
|
|
12
|
+
long_description=long_description,
|
|
13
|
+
long_description_content_type="text/markdown",
|
|
14
|
+
url="https://github.com/Nikhil-Singh-2503/JSONavigator", # Optional: Link to your repository
|
|
15
|
+
packages=find_packages(),
|
|
16
|
+
classifiers=[
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
],
|
|
21
|
+
python_requires=">=3.8",
|
|
22
|
+
install_requires=[], # Add any dependencies here if needed
|
|
23
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from jsoninja.core import traverse_json, get_value_at_path, find_all_paths_for_element
|
|
3
|
+
|
|
4
|
+
def test_traverse_json():
|
|
5
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
6
|
+
expected = [
|
|
7
|
+
("a.b[0]", 1),
|
|
8
|
+
("a.b[1]", 2),
|
|
9
|
+
("a.c", 3)
|
|
10
|
+
]
|
|
11
|
+
assert list(traverse_json(data)) == expected
|
|
12
|
+
|
|
13
|
+
def test_get_value_at_path():
|
|
14
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
15
|
+
assert get_value_at_path(data, "a.b[1]") == 2
|
|
16
|
+
assert get_value_at_path(data, "a.c") == 3
|
|
17
|
+
|
|
18
|
+
def test_find_all_paths_for_element():
|
|
19
|
+
data = {"a": {"b": [1, 2], "c": 3}, "d": {"b": 2}}
|
|
20
|
+
assert find_all_paths_for_element(data, 2) == ["a.b[1]", "d.b"]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from jsoninja.exceptions import InvalidPathError
|
|
3
|
+
from jsoninja.utils import (
|
|
4
|
+
validate_path,
|
|
5
|
+
format_path,
|
|
6
|
+
flatten_json,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
# Test cases for validate_path
|
|
10
|
+
def test_validate_path_valid():
|
|
11
|
+
"""
|
|
12
|
+
Test validating a properly formatted path.
|
|
13
|
+
"""
|
|
14
|
+
assert validate_path("a.b[1]") == True
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_validate_path_invalid_type():
|
|
18
|
+
"""
|
|
19
|
+
Test validating an invalid path type (not a string).
|
|
20
|
+
"""
|
|
21
|
+
with pytest.raises(InvalidPathError, match="Path must be a string."):
|
|
22
|
+
validate_path(123)==False # Path is not a string
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_validate_path_invalid_characters():
|
|
26
|
+
"""
|
|
27
|
+
Test validating a path with invalid characters.
|
|
28
|
+
"""
|
|
29
|
+
with pytest.raises(InvalidPathError, match="Invalid character '#' in path."):
|
|
30
|
+
validate_path("a.b#[1]")==False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_validate_path_mismatched_brackets():
|
|
34
|
+
"""
|
|
35
|
+
Test validating a path with mismatched brackets.
|
|
36
|
+
"""
|
|
37
|
+
with pytest.raises(InvalidPathError, match="Mismatched brackets in path."):
|
|
38
|
+
validate_path("a.b[1")==False
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Test cases for format_path
|
|
42
|
+
def test_format_path():
|
|
43
|
+
"""
|
|
44
|
+
Test formatting a path for better readability.
|
|
45
|
+
"""
|
|
46
|
+
assert format_path("a.b[1]") == "a -> b[1]"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_format_path_invalid_type():
|
|
50
|
+
"""
|
|
51
|
+
Test formatting an invalid path type (not a string).
|
|
52
|
+
"""
|
|
53
|
+
with pytest.raises(InvalidPathError, match="Path must be a string."):
|
|
54
|
+
format_path(123) # Path is not a string
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Test cases for flatten_json
|
|
58
|
+
def test_flatten_json():
|
|
59
|
+
"""
|
|
60
|
+
Test flattening a simple nested JSON structure.
|
|
61
|
+
"""
|
|
62
|
+
data = {"a": {"b": [1, 2], "c": 3}}
|
|
63
|
+
expected = {
|
|
64
|
+
"a.b[0]": 1,
|
|
65
|
+
"a.b[1]": 2,
|
|
66
|
+
"a.c": 3
|
|
67
|
+
}
|
|
68
|
+
assert flatten_json(data) == expected
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_flatten_json_empty():
|
|
72
|
+
"""
|
|
73
|
+
Test flattening an empty dictionary.
|
|
74
|
+
"""
|
|
75
|
+
data = {}
|
|
76
|
+
expected = {}
|
|
77
|
+
assert flatten_json(data) == expected
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_flatten_json_nested_lists():
|
|
81
|
+
"""
|
|
82
|
+
Test flattening a JSON structure with nested lists.
|
|
83
|
+
"""
|
|
84
|
+
data = {"a": [{"b": 1}, {"c": 2}]}
|
|
85
|
+
expected = {
|
|
86
|
+
"a[0].b": 1,
|
|
87
|
+
"a[1].c": 2
|
|
88
|
+
}
|
|
89
|
+
assert flatten_json(data) == expected
|