json-duplicate-keys 2024.4.20__tar.gz → 2024.11.19__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.
- {json-duplicate-keys-2024.4.20/json_duplicate_keys.egg-info → json-duplicate-keys-2024.11.19}/PKG-INFO +15 -11
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/README.md +14 -10
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/json_duplicate_keys/__init__.py +254 -288
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19/json_duplicate_keys.egg-info}/PKG-INFO +15 -11
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/setup.py +1 -1
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/LICENSE +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/MANIFEST.in +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/json_duplicate_keys.egg-info/SOURCES.txt +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/json_duplicate_keys.egg-info/dependency_links.txt +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/json_duplicate_keys.egg-info/top_level.txt +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/requirements.txt +0 -0
- {json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.11.19
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
5
|
Home-page: https://github.com/truocphan/json-duplicate-keys
|
6
6
|
Author: TP Cyber Security
|
@@ -16,12 +16,6 @@ Description: # JSON Duplicate Keys - PyPI
|
|
16
16
|
<a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
|
17
17
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/truocphan/json-duplicate-keys" height=30></a>
|
18
18
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/truocphan/json-duplicate-keys" height=30></a>
|
19
|
-
<a href="https://pypi.org/project/json-duplicate-keys/" target="_blank"><img src="https://img.shields.io/badge/pypi-3775A9?style=for-the-badge&logo=pypi&logoColor=white" height=30></a>
|
20
|
-
<a href="https://www.facebook.com/61550595106970" target="_blank"><img src="https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white" height=30></a>
|
21
|
-
<a href="https://twitter.com/TPCyberSec" target="_blank"><img src="https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white" height=30></a>
|
22
|
-
<a href="https://github.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white" height=30></a>
|
23
|
-
<a href="mailto:tpcybersec2023@gmail.com" target="_blank"><img src="https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white" height=30></a>
|
24
|
-
<a href="https://www.buymeacoffee.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" height=30></a>
|
25
19
|
</p>
|
26
20
|
|
27
21
|
## Installation
|
@@ -106,9 +100,10 @@ Description: # JSON Duplicate Keys - PyPI
|
|
106
100
|
```
|
107
101
|
---
|
108
102
|
|
109
|
-
### JSON_DUPLICATE_KEYS.get(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
103
|
+
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
110
104
|
_Get value in the JSON object by `name`_
|
111
105
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
106
|
+
- `case_insensitive`: the key name case (in)sensitive
|
112
107
|
- `separator`:
|
113
108
|
- `parse_index`:
|
114
109
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -130,10 +125,11 @@ Description: # JSON Duplicate Keys - PyPI
|
|
130
125
|
```
|
131
126
|
---
|
132
127
|
|
133
|
-
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
128
|
+
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
134
129
|
_Set a new `name` and `value` for the JSON object_
|
135
130
|
- `name`: new key name for the JSON object. Supported flat key name format
|
136
131
|
- `value`: value for key `name`
|
132
|
+
- `case_insensitive`: the key name case (in)sensitive
|
137
133
|
- `separator`:
|
138
134
|
- `parse_index`:
|
139
135
|
- `dupSign_start`:
|
@@ -194,10 +190,11 @@ Description: # JSON Duplicate Keys - PyPI
|
|
194
190
|
```
|
195
191
|
---
|
196
192
|
|
197
|
-
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
193
|
+
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
198
194
|
_Update new `value` for existing `name` in the JSON object_
|
199
195
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
200
196
|
- `value`: new value for key `name`
|
197
|
+
- `case_insensitive`: the key name case (in)sensitive
|
201
198
|
- `separator`:
|
202
199
|
- `parse_index`:
|
203
200
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -219,9 +216,10 @@ Description: # JSON Duplicate Keys - PyPI
|
|
219
216
|
```
|
220
217
|
---
|
221
218
|
|
222
|
-
### JSON_DUPLICATE_KEYS.delete(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
219
|
+
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
223
220
|
_Delete a key-value pair in a JSON object by key `name`_
|
224
221
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
222
|
+
- `case_insensitive`: the key name case (in)sensitive
|
225
223
|
- `separator`:
|
226
224
|
- `parse_index`:
|
227
225
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -388,6 +386,12 @@ Description: # JSON Duplicate Keys - PyPI
|
|
388
386
|
---
|
389
387
|
|
390
388
|
## CHANGELOG
|
389
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.19)
|
390
|
+
- **Updated**: Allows getting (`JSON_DUPLICATE_KEYS.get`), setting (`JSON_DUPLICATE_KEYS.set`), updating (`JSON_DUPLICATE_KEYS.update`), deleting (`JSON_DUPLICATE_KEYS.delete`) JSON_DUPLICATE_KEYS objects with case-insensitive key names
|
391
|
+
|
392
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/truocphan/json-duplicate-keys/tree/2024.7.17)
|
393
|
+
- **Fixed**: issue [#3](https://github.com/truocphan/json-duplicate-keys/issues/3) break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
394
|
+
|
391
395
|
#### [json-duplicate-keys v2024.4.20](https://github.com/truocphan/json-duplicate-keys/tree/2024.4.20)
|
392
396
|
- **New**: _filter_values_
|
393
397
|
- **Updated**: _filter_keys_
|
@@ -8,12 +8,6 @@ Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
|
8
8
|
<a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
|
9
9
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/truocphan/json-duplicate-keys" height=30></a>
|
10
10
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/truocphan/json-duplicate-keys" height=30></a>
|
11
|
-
<a href="https://pypi.org/project/json-duplicate-keys/" target="_blank"><img src="https://img.shields.io/badge/pypi-3775A9?style=for-the-badge&logo=pypi&logoColor=white" height=30></a>
|
12
|
-
<a href="https://www.facebook.com/61550595106970" target="_blank"><img src="https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white" height=30></a>
|
13
|
-
<a href="https://twitter.com/TPCyberSec" target="_blank"><img src="https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white" height=30></a>
|
14
|
-
<a href="https://github.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white" height=30></a>
|
15
|
-
<a href="mailto:tpcybersec2023@gmail.com" target="_blank"><img src="https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white" height=30></a>
|
16
|
-
<a href="https://www.buymeacoffee.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" height=30></a>
|
17
11
|
</p>
|
18
12
|
|
19
13
|
## Installation
|
@@ -98,9 +92,10 @@ print(JDKSObject.getObject())
|
|
98
92
|
```
|
99
93
|
---
|
100
94
|
|
101
|
-
### JSON_DUPLICATE_KEYS.get(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
95
|
+
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
102
96
|
_Get value in the JSON object by `name`_
|
103
97
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
98
|
+
- `case_insensitive`: the key name case (in)sensitive
|
104
99
|
- `separator`:
|
105
100
|
- `parse_index`:
|
106
101
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -122,10 +117,11 @@ print(JDKSObject.get("snapshot||author"))
|
|
122
117
|
```
|
123
118
|
---
|
124
119
|
|
125
|
-
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
120
|
+
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
126
121
|
_Set a new `name` and `value` for the JSON object_
|
127
122
|
- `name`: new key name for the JSON object. Supported flat key name format
|
128
123
|
- `value`: value for key `name`
|
124
|
+
- `case_insensitive`: the key name case (in)sensitive
|
129
125
|
- `separator`:
|
130
126
|
- `parse_index`:
|
131
127
|
- `dupSign_start`:
|
@@ -186,10 +182,11 @@ print(JDKSObject.getObject())
|
|
186
182
|
```
|
187
183
|
---
|
188
184
|
|
189
|
-
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
185
|
+
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
190
186
|
_Update new `value` for existing `name` in the JSON object_
|
191
187
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
192
188
|
- `value`: new value for key `name`
|
189
|
+
- `case_insensitive`: the key name case (in)sensitive
|
193
190
|
- `separator`:
|
194
191
|
- `parse_index`:
|
195
192
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -211,9 +208,10 @@ print(JDKSObject.getObject())
|
|
211
208
|
```
|
212
209
|
---
|
213
210
|
|
214
|
-
### JSON_DUPLICATE_KEYS.delete(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
211
|
+
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
215
212
|
_Delete a key-value pair in a JSON object by key `name`_
|
216
213
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
214
|
+
- `case_insensitive`: the key name case (in)sensitive
|
217
215
|
- `separator`:
|
218
216
|
- `parse_index`:
|
219
217
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -380,6 +378,12 @@ print(JDKSObject.getObject())
|
|
380
378
|
---
|
381
379
|
|
382
380
|
## CHANGELOG
|
381
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.19)
|
382
|
+
- **Updated**: Allows getting (`JSON_DUPLICATE_KEYS.get`), setting (`JSON_DUPLICATE_KEYS.set`), updating (`JSON_DUPLICATE_KEYS.update`), deleting (`JSON_DUPLICATE_KEYS.delete`) JSON_DUPLICATE_KEYS objects with case-insensitive key names
|
383
|
+
|
384
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/truocphan/json-duplicate-keys/tree/2024.7.17)
|
385
|
+
- **Fixed**: issue [#3](https://github.com/truocphan/json-duplicate-keys/issues/3) break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
386
|
+
|
383
387
|
#### [json-duplicate-keys v2024.4.20](https://github.com/truocphan/json-duplicate-keys/tree/2024.4.20)
|
384
388
|
- **New**: _filter_values_
|
385
389
|
- **Updated**: _filter_keys_
|
{json-duplicate-keys-2024.4.20 → json-duplicate-keys-2024.11.19}/json_duplicate_keys/__init__.py
RENAMED
@@ -1,3 +1,8 @@
|
|
1
|
+
try:
|
2
|
+
unicode # Python 2
|
3
|
+
except NameError:
|
4
|
+
unicode = str # Python 3
|
5
|
+
|
1
6
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
2
7
|
# # # # # # # # # # # Normalize Key name # # # # # # # # # # #
|
3
8
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -6,18 +11,16 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
|
|
6
11
|
|
7
12
|
# User input data type validation
|
8
13
|
if type(_isDebug_) != bool: _isDebug_ = False
|
9
|
-
try:
|
10
|
-
if type(name) not in [str, unicode]:
|
11
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
12
|
-
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
13
|
-
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
14
|
-
except Exception as e:
|
15
|
-
if type(name) not in [str]:
|
16
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
17
|
-
if type(dupSign_start) not in [str]: dupSign_start = "{{{"
|
18
|
-
if type(dupSign_end) not in [str]: dupSign_end = "}}}"
|
19
14
|
|
20
|
-
|
15
|
+
if type(name) not in [str, unicode]:
|
16
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
17
|
+
return False
|
18
|
+
|
19
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
20
|
+
|
21
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
22
|
+
|
23
|
+
return re.sub('{dupSign_start}_\\d+_{dupSign_end}$'.format(dupSign_start=re.escape(dupSign_start), dupSign_end=re.escape(dupSign_end)), "", name)
|
21
24
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
22
25
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
23
26
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -32,22 +35,21 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
32
35
|
|
33
36
|
# User input data type validation
|
34
37
|
if type(_isDebug_) != bool: _isDebug_ = False
|
38
|
+
|
35
39
|
if type(ordered_dict) != bool: ordered_dict = False
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if type(dupSign_start) not in [str]: dupSign_start = "{{{"
|
45
|
-
if type(dupSign_end) not in [str]: dupSign_end = "}}}"
|
40
|
+
|
41
|
+
if type(Jstr) not in [str, unicode]:
|
42
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
|
43
|
+
return False
|
44
|
+
|
45
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
46
|
+
|
47
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
46
48
|
|
47
49
|
def __convert_Jloads_to_Jobj(Jloads, Jobj):
|
48
50
|
if type(Jloads) in [dict, OrderedDict]:
|
49
51
|
for k in Jloads.keys():
|
50
|
-
_key = re.split(dupSign_start_escape_regex+"_
|
52
|
+
_key = re.split(dupSign_start_escape_regex+"_\\d+_"+dupSign_end_escape_regex+"$", k)[0]
|
51
53
|
|
52
54
|
if _key not in Jobj.keys():
|
53
55
|
if type(Jloads[k]) not in [list, dict, OrderedDict]:
|
@@ -62,7 +64,7 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
62
64
|
|
63
65
|
__convert_Jloads_to_Jobj(Jloads[k], Jobj[_key])
|
64
66
|
else:
|
65
|
-
countObj = len([i for i in Jobj.keys() if _key==re.split(dupSign_start_escape_regex+"_
|
67
|
+
countObj = len([i for i in Jobj.keys() if _key==re.split(dupSign_start_escape_regex+"_\\d+_"+dupSign_end_escape_regex+"$", i)[0]])
|
66
68
|
if type(Jloads[k]) not in [list, dict, OrderedDict]:
|
67
69
|
Jobj[_key+dupSign_start+"_"+str(countObj+1)+"_"+dupSign_end] = Jloads[k]
|
68
70
|
else:
|
@@ -90,8 +92,7 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
90
92
|
|
91
93
|
try:
|
92
94
|
Jloads = json.loads(Jstr)
|
93
|
-
if ordered_dict:
|
94
|
-
Jloads = json.loads(Jstr, object_pairs_hook=OrderedDict)
|
95
|
+
if ordered_dict: Jloads = json.loads(Jstr, object_pairs_hook=OrderedDict)
|
95
96
|
|
96
97
|
if type(Jloads) in [list, dict, OrderedDict]:
|
97
98
|
dupSign_start_escape = "".join(["\\\\u"+hex(ord(c))[2:].zfill(4) for c in dupSign_start])
|
@@ -135,8 +136,10 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
135
136
|
return JSON_DUPLICATE_KEYS(Jobj)
|
136
137
|
else:
|
137
138
|
if _isDebug_: print("\x1b[31m[-] DataError: Invalid JSON format\x1b[0m")
|
139
|
+
return False
|
138
140
|
except Exception as e:
|
139
141
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
142
|
+
return False
|
140
143
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
141
144
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
142
145
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -154,6 +157,7 @@ def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False,
|
|
154
157
|
return loads(Jstr, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, _isDebug_=_isDebug_)
|
155
158
|
except Exception as e:
|
156
159
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
160
|
+
return False
|
157
161
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
158
162
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
159
163
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -183,46 +187,57 @@ class JSON_DUPLICATE_KEYS:
|
|
183
187
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
184
188
|
# # # # # # # # # # # # # # # get # # # # # # # # # # # # # # #
|
185
189
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
186
|
-
def get(self, name, separator="||", parse_index="$", _isDebug_=False):
|
190
|
+
def get(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
187
191
|
import re
|
188
192
|
from collections import OrderedDict
|
189
193
|
|
190
194
|
# User input data type validation
|
191
195
|
if type(_isDebug_) != bool: _isDebug_ = False
|
192
|
-
try:
|
193
|
-
if type(name) not in [str, unicode]:
|
194
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
195
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
196
|
-
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
197
|
-
except Exception as e:
|
198
|
-
if type(name) not in [str]:
|
199
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
200
|
-
if type(separator) not in [str]: separator = "||"
|
201
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
202
196
|
|
203
|
-
if type(
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
Jval = Jobj[int(name_split[i].split(parse_index)[1])]
|
215
|
-
Jobj = Jobj[int(name_split[i].split(parse_index)[1])]
|
216
|
-
else:
|
217
|
-
if _isDebug_: print("\x1b[31m[-] KeyNotFoundError: \x1b[0m"+separator.join(name_split[:i+1]))
|
218
|
-
return "JSON_DUPLICATE_KEYS_ERROR"
|
219
|
-
return Jval
|
220
|
-
except Exception as e:
|
221
|
-
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
222
|
-
return "JSON_DUPLICATE_KEYS_ERROR"
|
223
|
-
else:
|
197
|
+
if type(name) not in [str, unicode]:
|
198
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
199
|
+
return {"name":name, "value":"JSON_DUPLICATE_KEYS_ERROR"}
|
200
|
+
|
201
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
202
|
+
|
203
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
204
|
+
|
205
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
206
|
+
|
207
|
+
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
224
208
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
225
|
-
return "JSON_DUPLICATE_KEYS_ERROR"
|
209
|
+
return {"name":name, "value":"JSON_DUPLICATE_KEYS_ERROR"}
|
210
|
+
|
211
|
+
if re.search(re.escape(separator)+"$", name):
|
212
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
213
|
+
return {"name":name, "value":"JSON_DUPLICATE_KEYS_ERROR"}
|
214
|
+
|
215
|
+
Jobj = JSON_DUPLICATE_KEYS(self.__Jobj)
|
216
|
+
Jobj.flatten()
|
217
|
+
Jname = []
|
218
|
+
Jval = self.__Jobj
|
219
|
+
name_split = name.split(separator)
|
220
|
+
for k in Jobj.getObject().keys():
|
221
|
+
if len(k.split(separator)) >= len(name_split):
|
222
|
+
if case_insensitive:
|
223
|
+
if separator.join(k.split(separator)[:len(name_split)]).lower() == name.lower():
|
224
|
+
Jname = k.split(separator)[:len(name_split)]
|
225
|
+
break
|
226
|
+
else:
|
227
|
+
if separator.join(k.split(separator)[:len(name_split)]) == name:
|
228
|
+
Jname = name_split
|
229
|
+
break
|
230
|
+
|
231
|
+
if len(Jname) > 0:
|
232
|
+
for k in Jname:
|
233
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
234
|
+
Jval = Jval[int(k.split(parse_index)[1])]
|
235
|
+
else:
|
236
|
+
Jval = Jval[k]
|
237
|
+
return {"name":separator.join(Jname), "value":Jval}
|
238
|
+
else:
|
239
|
+
if _isDebug_: print("\x1b[31m[-] KeyNotFoundError: \x1b[0m"+name)
|
240
|
+
return {"name":name, "value":"JSON_DUPLICATE_KEYS_ERROR"}
|
226
241
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
227
242
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
228
243
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -231,133 +246,80 @@ class JSON_DUPLICATE_KEYS:
|
|
231
246
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
232
247
|
# # # # # # # # # # # # # # # set # # # # # # # # # # # # # # #
|
233
248
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
234
|
-
def set(self, name, value, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
|
249
|
+
def set(self, name, value, case_insensitive=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
|
235
250
|
import re
|
236
251
|
from collections import OrderedDict
|
237
252
|
|
238
253
|
# User input data type validation
|
239
254
|
if type(_isDebug_) != bool: _isDebug_ = False
|
255
|
+
|
240
256
|
if type(ordered_dict) != bool: ordered_dict = False
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
if type(self.getObject()) in [list, dict, OrderedDict]:
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
else if typeof self.getObject() is dict
|
283
|
-
=> Add new key ( self.__Jobj[name_split_lastKey] = value )
|
284
|
-
"""
|
285
|
-
# Add duplicate key
|
286
|
-
if self.get(separator.join(name_split), separator=separator, parse_index=parse_index) != "JSON_DUPLICATE_KEYS_ERROR":
|
287
|
-
index = 2
|
288
|
-
while True:
|
289
|
-
if self.get(separator.join(name_split)+dupSign_start+"_"+str(index)+"_"+dupSign_end, separator=separator, parse_index=parse_index) == "JSON_DUPLICATE_KEYS_ERROR":
|
290
|
-
break
|
291
|
-
index += 1
|
292
|
-
|
293
|
-
exec_expression = "self.getObject()"
|
294
|
-
|
295
|
-
name_split[-1] = name_split[-1]+dupSign_start+"_"+str(index)+"_"+dupSign_end
|
296
|
-
for k in name_split:
|
297
|
-
if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
|
298
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
299
|
-
else:
|
300
|
-
exec_expression += "["+repr(k)+"]"
|
301
|
-
|
302
|
-
exec(exec_expression+"="+repr(value))
|
303
|
-
return True
|
304
|
-
# Add new key
|
305
|
-
elif self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index) != "JSON_DUPLICATE_KEYS_ERROR":
|
306
|
-
if type(self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index)) == list:
|
307
|
-
if name_split_lastKey == "":
|
308
|
-
exec_expression = "self.getObject()"
|
309
|
-
|
310
|
-
for k in name_split_first:
|
311
|
-
if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
|
312
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
313
|
-
else:
|
314
|
-
exec_expression += "["+repr(k)+"]"
|
315
|
-
|
316
|
-
exec(exec_expression+".append("+repr(value)+")")
|
317
|
-
else:
|
318
|
-
exec_expression = "self.getObject()"
|
319
|
-
|
320
|
-
for k in name_split_first:
|
321
|
-
if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
|
322
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
323
|
-
else:
|
324
|
-
exec_expression += "["+repr(k)+"]"
|
325
|
-
|
326
|
-
exec(exec_expression+".append({"+repr(name_split_lastKey)+":"+repr(value)+"})")
|
327
|
-
return True
|
328
|
-
elif type(self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index)) == dict:
|
329
|
-
exec_expression = "self.getObject()"
|
330
|
-
|
331
|
-
for k in name_split_first:
|
332
|
-
if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
|
333
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
334
|
-
else:
|
335
|
-
exec_expression += "["+repr(k)+"]"
|
336
|
-
|
337
|
-
exec(exec_expression+"["+repr(name_split_lastKey)+"]="+repr(value))
|
338
|
-
return True
|
339
|
-
else:
|
340
|
-
if _isDebug_: print("\x1b[31m[-] KeyNameNotExistError: {}\x1b[0m".format(separator.join(name_split_first)))
|
341
|
-
# Add new key
|
342
|
-
elif len(name_split_first) == 0:
|
343
|
-
if type(self.getObject()) == list:
|
344
|
-
if name_split_lastKey == "":
|
345
|
-
self.__Jobj.append(value)
|
346
|
-
else:
|
347
|
-
self.__Jobj.append({name_split_lastKey: value})
|
348
|
-
else:
|
349
|
-
self.__Jobj[name_split_lastKey] = value
|
350
|
-
return True
|
351
|
-
else:
|
352
|
-
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: {}\x1b[0m".format(separator.join(name_split_first)))
|
257
|
+
|
258
|
+
if type(name) not in [str, unicode]:
|
259
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
260
|
+
return False
|
261
|
+
|
262
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
263
|
+
|
264
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
265
|
+
|
266
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
267
|
+
|
268
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
269
|
+
|
270
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
271
|
+
|
272
|
+
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
273
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
274
|
+
return False
|
275
|
+
|
276
|
+
if re.search(re.escape(separator)+"$", name):
|
277
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
278
|
+
return False
|
279
|
+
|
280
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", name.split(separator)[-1]):
|
281
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: The key name does not end with the list index\x1b[0m")
|
282
|
+
return False
|
283
|
+
|
284
|
+
Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)
|
285
|
+
|
286
|
+
if Jget["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
287
|
+
index = 2
|
288
|
+
while True:
|
289
|
+
if self.get(Jget["name"]+dupSign_start+"_"+str(index)+"_"+dupSign_end, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["value"] == "JSON_DUPLICATE_KEYS_ERROR":
|
290
|
+
break
|
291
|
+
index += 1
|
292
|
+
|
293
|
+
exec_expression = "self.getObject()"
|
294
|
+
|
295
|
+
for k in (Jget["name"]+dupSign_start+"_"+str(index)+"_"+dupSign_end).split(separator):
|
296
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
297
|
+
exec_expression += "["+k.split(parse_index)[1]+"]"
|
353
298
|
else:
|
354
|
-
|
355
|
-
|
356
|
-
|
299
|
+
exec_expression += "["+repr(k)+"]"
|
300
|
+
|
301
|
+
exec(exec_expression+"="+repr(value))
|
302
|
+
return True
|
357
303
|
else:
|
358
|
-
if
|
304
|
+
if len(name.split(separator)) == 1:
|
305
|
+
self.getObject()[name] = value
|
306
|
+
return True
|
307
|
+
else:
|
308
|
+
if self.get(separator.join(name.split(separator)[:-1]), case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
309
|
+
Jget = self.get(separator.join(name.split(separator)[:-1]), case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)
|
310
|
+
exec_expression = "self.getObject()"
|
359
311
|
|
360
|
-
|
312
|
+
for k in Jget["name"].split(separator):
|
313
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
314
|
+
exec_expression += "["+k.split(parse_index)[1]+"]"
|
315
|
+
else:
|
316
|
+
exec_expression += "["+repr(k)+"]"
|
317
|
+
|
318
|
+
exec(exec_expression+"="+repr(value))
|
319
|
+
return True
|
320
|
+
else:
|
321
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameNotExistError: {}\x1b[0m".format(separator.join(Jget["name"].split(separator)[:-1])))
|
322
|
+
return False
|
361
323
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
362
324
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
363
325
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -366,28 +328,29 @@ class JSON_DUPLICATE_KEYS:
|
|
366
328
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
367
329
|
# # # # # # # # # # # # # # update # # # # # # # # # # # # # #
|
368
330
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
369
|
-
def update(self, name, value, separator="||", parse_index="$", _isDebug_=False):
|
331
|
+
def update(self, name, value, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
370
332
|
import re
|
371
333
|
|
372
334
|
# User input data type validation
|
373
335
|
if type(_isDebug_) != bool: _isDebug_ = False
|
374
|
-
try:
|
375
|
-
if type(name) not in [str, unicode]:
|
376
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
377
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
378
|
-
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
379
|
-
except Exception as e:
|
380
|
-
if type(name) not in [str]:
|
381
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
382
|
-
if type(separator) not in [str]: separator = "||"
|
383
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
384
336
|
|
385
|
-
if
|
337
|
+
if type(name) not in [str, unicode]:
|
338
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
339
|
+
return False
|
340
|
+
|
341
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
342
|
+
|
343
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
344
|
+
|
345
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
346
|
+
|
347
|
+
if self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_)["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
348
|
+
Jname = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["name"]
|
386
349
|
try:
|
387
350
|
exec_expression = "self.getObject()"
|
388
351
|
|
389
|
-
for k in
|
390
|
-
if re.search("^"+re.escape(parse_index)+"
|
352
|
+
for k in Jname.split(separator):
|
353
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
391
354
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
392
355
|
else:
|
393
356
|
exec_expression += "["+repr(k)+"]"
|
@@ -406,29 +369,29 @@ class JSON_DUPLICATE_KEYS:
|
|
406
369
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
407
370
|
# # # # # # # # # # # # # # delete # # # # # # # # # # # # #
|
408
371
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
409
|
-
def delete(self, name, separator="||", parse_index="$", _isDebug_=False):
|
372
|
+
def delete(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
410
373
|
import re
|
411
374
|
|
412
375
|
# User input data type validation
|
413
376
|
if type(_isDebug_) != bool: _isDebug_ = False
|
414
377
|
|
415
|
-
|
416
|
-
if
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
423
|
-
if type(separator) not in [str]: separator = "||"
|
424
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
378
|
+
if type(name) not in [str, unicode]:
|
379
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
380
|
+
return False
|
381
|
+
|
382
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
383
|
+
|
384
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
425
385
|
|
426
|
-
if
|
386
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
387
|
+
|
388
|
+
if self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_)["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
389
|
+
Jname = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["name"]
|
427
390
|
try:
|
428
391
|
exec_expression = "del self.getObject()"
|
429
392
|
|
430
|
-
for k in
|
431
|
-
if re.search("^"+re.escape(parse_index)+"
|
393
|
+
for k in Jname.split(separator):
|
394
|
+
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
432
395
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
433
396
|
else:
|
434
397
|
exec_expression += "["+repr(k)+"]"
|
@@ -457,10 +420,10 @@ class JSON_DUPLICATE_KEYS:
|
|
457
420
|
for k, v in JDKSObject.getObject().items():
|
458
421
|
if type(k) == str and type(name) == str:
|
459
422
|
if re.search(name, k):
|
460
|
-
newJDKSObject.set(k, v, separator="
|
423
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
461
424
|
else:
|
462
425
|
if name == k:
|
463
|
-
newJDKSObject.set(k, v, separator="
|
426
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
464
427
|
|
465
428
|
return newJDKSObject
|
466
429
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -481,10 +444,10 @@ class JSON_DUPLICATE_KEYS:
|
|
481
444
|
for k, v in JDKSObject.getObject().items():
|
482
445
|
if type(v) == str and type(value) == str:
|
483
446
|
if re.search(value, v):
|
484
|
-
newJDKSObject.set(k, v, separator="
|
447
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
485
448
|
else:
|
486
449
|
if value == v:
|
487
|
-
newJDKSObject.set(k, v, separator="
|
450
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
488
451
|
|
489
452
|
return newJDKSObject
|
490
453
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -501,22 +464,20 @@ class JSON_DUPLICATE_KEYS:
|
|
501
464
|
|
502
465
|
# User input data type validation
|
503
466
|
if type(_isDebug_) != bool: _isDebug_ = False
|
504
|
-
try:
|
505
|
-
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
506
|
-
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
507
|
-
except Exception as e:
|
508
|
-
if type(dupSign_start) not in [str]: dupSign_start = "{{{"
|
509
|
-
if type(dupSign_end) not in [str]: dupSign_end = "}}}"
|
510
467
|
|
511
|
-
if type(
|
512
|
-
dupSign_start_escape_regex = re.escape(json.dumps({dupSign_start:""})[2:-6])
|
468
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
513
469
|
|
514
|
-
|
470
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
515
471
|
|
516
|
-
|
517
|
-
else:
|
472
|
+
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
518
473
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
519
474
|
return "JSON_DUPLICATE_KEYS_ERROR"
|
475
|
+
|
476
|
+
dupSign_start_escape_regex = re.escape(json.dumps({dupSign_start:""})[2:-6])
|
477
|
+
|
478
|
+
dupSign_end_escape_regex = re.escape(json.dumps({dupSign_end:""})[2:-6])
|
479
|
+
|
480
|
+
return re.sub('{dupSign_start}_\\d+_{dupSign_end}":'.format(dupSign_start=dupSign_start_escape_regex, dupSign_end=dupSign_end_escape_regex), '":', json.dumps(self.getObject(), skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular, allow_nan=allow_nan, cls=cls, indent=indent, separators=separators, default=default, sort_keys=sort_keys))
|
520
481
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
521
482
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
522
483
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -534,6 +495,7 @@ class JSON_DUPLICATE_KEYS:
|
|
534
495
|
Jfile.close()
|
535
496
|
except Exception as e:
|
536
497
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
498
|
+
return False
|
537
499
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
538
500
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
539
501
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -547,52 +509,54 @@ class JSON_DUPLICATE_KEYS:
|
|
547
509
|
|
548
510
|
# User input data type validation
|
549
511
|
if type(_isDebug_) != bool: _isDebug_ = False
|
512
|
+
|
550
513
|
if type(ordered_dict) != bool: ordered_dict = False
|
551
|
-
try:
|
552
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
553
|
-
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
554
|
-
except Exception as e:
|
555
|
-
if type(separator) not in [str]: separator = "||"
|
556
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
557
|
-
|
558
|
-
if type(self.getObject()) in [list, dict, OrderedDict]:
|
559
|
-
if len(self.getObject()) > 0:
|
560
|
-
try:
|
561
|
-
Jflat = dict()
|
562
|
-
if ordered_dict:
|
563
|
-
Jflat = OrderedDict()
|
564
|
-
|
565
|
-
def __convert_Jobj_to_Jflat(Jobj, key=None):
|
566
|
-
if type(Jobj) in [dict, OrderedDict]:
|
567
|
-
if len(Jobj) == 0:
|
568
|
-
Jflat[key] = dict()
|
569
|
-
if ordered_dict:
|
570
|
-
Jflat[key] = OrderedDict()
|
571
|
-
else:
|
572
|
-
for k,v in Jobj.items():
|
573
|
-
_Jobj = v
|
574
|
-
_key = "{key}{separator}{k}".format(key=key,separator=separator,k=k) if key != None else "{k}".format(k=k)
|
575
|
-
|
576
|
-
__convert_Jobj_to_Jflat(_Jobj, _key)
|
577
|
-
elif type(Jobj) == list:
|
578
|
-
if len(Jobj) == 0:
|
579
|
-
Jflat[key] = list()
|
580
|
-
else:
|
581
|
-
for i,v in enumerate(Jobj):
|
582
|
-
_Jobj = v
|
583
|
-
_key = "{key}{separator}{parse_index}{i}{parse_index}".format(key=key, separator=separator, parse_index=parse_index, i=i) if key != None else "{parse_index}{i}{parse_index}".format(parse_index=parse_index, i=i)
|
584
|
-
|
585
|
-
__convert_Jobj_to_Jflat(_Jobj, _key)
|
586
|
-
else:
|
587
|
-
Jflat[key] = Jobj
|
588
514
|
|
589
|
-
|
515
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
590
516
|
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
else:
|
517
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
518
|
+
|
519
|
+
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
595
520
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
521
|
+
return False
|
522
|
+
|
523
|
+
if len(self.getObject()) > 0:
|
524
|
+
try:
|
525
|
+
Jflat = dict()
|
526
|
+
if ordered_dict:
|
527
|
+
Jflat = OrderedDict()
|
528
|
+
|
529
|
+
def __convert_Jobj_to_Jflat(Jobj, key=None):
|
530
|
+
if type(Jobj) in [dict, OrderedDict]:
|
531
|
+
if len(Jobj) == 0:
|
532
|
+
Jflat[key] = dict()
|
533
|
+
if ordered_dict:
|
534
|
+
Jflat[key] = OrderedDict()
|
535
|
+
else:
|
536
|
+
for k,v in Jobj.items():
|
537
|
+
_Jobj = v
|
538
|
+
_key = "{key}{separator}{k}".format(key=key,separator=separator,k=k) if key != None else "{k}".format(k=k)
|
539
|
+
|
540
|
+
__convert_Jobj_to_Jflat(_Jobj, _key)
|
541
|
+
elif type(Jobj) == list:
|
542
|
+
if len(Jobj) == 0:
|
543
|
+
Jflat[key] = list()
|
544
|
+
else:
|
545
|
+
for i,v in enumerate(Jobj):
|
546
|
+
_Jobj = v
|
547
|
+
_key = "{key}{separator}{parse_index}{i}{parse_index}".format(key=key, separator=separator, parse_index=parse_index, i=i) if key != None else "{parse_index}{i}{parse_index}".format(parse_index=parse_index, i=i)
|
548
|
+
|
549
|
+
__convert_Jobj_to_Jflat(_Jobj, _key)
|
550
|
+
else:
|
551
|
+
Jflat[key] = Jobj
|
552
|
+
|
553
|
+
__convert_Jobj_to_Jflat(self.getObject())
|
554
|
+
|
555
|
+
self.__Jobj = Jflat
|
556
|
+
return True
|
557
|
+
except Exception as e:
|
558
|
+
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
559
|
+
return False
|
596
560
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
597
561
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
598
562
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -607,42 +571,44 @@ class JSON_DUPLICATE_KEYS:
|
|
607
571
|
|
608
572
|
# User input data type validation
|
609
573
|
if type(_isDebug_) != bool: _isDebug_ = False
|
574
|
+
|
610
575
|
if type(ordered_dict) != bool: ordered_dict = False
|
611
|
-
try:
|
612
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
613
|
-
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
614
|
-
except Exception as e:
|
615
|
-
if type(separator) not in [str]: separator = "||"
|
616
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
617
576
|
|
618
|
-
if type(
|
619
|
-
if len(self.getObject()) > 0:
|
620
|
-
try:
|
621
|
-
Jobj = list() if len([k for k in self.__Jobj.keys() if re.compile("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$").match(str(k).split(separator)[0])]) == len(self.__Jobj.keys()) else OrderedDict() if ordered_dict else dict()
|
577
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
622
578
|
|
623
|
-
|
624
|
-
Jtmp = Jobj
|
625
|
-
Jkeys = k.split(separator)
|
579
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
626
580
|
|
627
|
-
|
628
|
-
|
581
|
+
if type(self.getObject()) not in [dict, OrderedDict]:
|
582
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
583
|
+
return False
|
629
584
|
|
630
|
-
|
631
|
-
|
585
|
+
if len(self.getObject()) > 0:
|
586
|
+
try:
|
587
|
+
Jobj = list() if len([k for k in self.__Jobj.keys() if re.compile("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$").match(str(k).split(separator)[0])]) == len(self.__Jobj.keys()) else OrderedDict() if ordered_dict else dict()
|
632
588
|
|
633
|
-
|
634
|
-
|
589
|
+
for k, v in self.__Jobj.items():
|
590
|
+
Jtmp = Jobj
|
591
|
+
Jkeys = k.split(separator)
|
635
592
|
|
636
|
-
|
637
|
-
|
593
|
+
for count, (Jkey, next_Jkeys) in enumerate(zip(Jkeys, Jkeys[1:] + [v]), 1):
|
594
|
+
v = next_Jkeys if count == len(Jkeys) else list() if re.compile("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$").match(next_Jkeys) else OrderedDict() if ordered_dict else dict()
|
638
595
|
|
639
|
-
|
596
|
+
if type(Jtmp) == list:
|
597
|
+
Jkey = int(re.compile(re.escape(parse_index)+"(\\d+)"+re.escape(parse_index)).match(Jkey).group(1))
|
640
598
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
599
|
+
while Jkey >= len(Jtmp):
|
600
|
+
Jtmp.append(v)
|
601
|
+
|
602
|
+
elif Jkey not in Jtmp:
|
603
|
+
Jtmp[Jkey] = v
|
604
|
+
|
605
|
+
Jtmp = Jtmp[Jkey]
|
606
|
+
|
607
|
+
self.__Jobj = Jobj
|
608
|
+
return True
|
609
|
+
except Exception as e:
|
610
|
+
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
611
|
+
return False
|
646
612
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
647
613
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
648
614
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.11.19
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
5
|
Home-page: https://github.com/truocphan/json-duplicate-keys
|
6
6
|
Author: TP Cyber Security
|
@@ -16,12 +16,6 @@ Description: # JSON Duplicate Keys - PyPI
|
|
16
16
|
<a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
|
17
17
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/truocphan/json-duplicate-keys" height=30></a>
|
18
18
|
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/truocphan/json-duplicate-keys" height=30></a>
|
19
|
-
<a href="https://pypi.org/project/json-duplicate-keys/" target="_blank"><img src="https://img.shields.io/badge/pypi-3775A9?style=for-the-badge&logo=pypi&logoColor=white" height=30></a>
|
20
|
-
<a href="https://www.facebook.com/61550595106970" target="_blank"><img src="https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white" height=30></a>
|
21
|
-
<a href="https://twitter.com/TPCyberSec" target="_blank"><img src="https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white" height=30></a>
|
22
|
-
<a href="https://github.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white" height=30></a>
|
23
|
-
<a href="mailto:tpcybersec2023@gmail.com" target="_blank"><img src="https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white" height=30></a>
|
24
|
-
<a href="https://www.buymeacoffee.com/truocphan" target="_blank"><img src="https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" height=30></a>
|
25
19
|
</p>
|
26
20
|
|
27
21
|
## Installation
|
@@ -106,9 +100,10 @@ Description: # JSON Duplicate Keys - PyPI
|
|
106
100
|
```
|
107
101
|
---
|
108
102
|
|
109
|
-
### JSON_DUPLICATE_KEYS.get(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
103
|
+
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
110
104
|
_Get value in the JSON object by `name`_
|
111
105
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
106
|
+
- `case_insensitive`: the key name case (in)sensitive
|
112
107
|
- `separator`:
|
113
108
|
- `parse_index`:
|
114
109
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -130,10 +125,11 @@ Description: # JSON Duplicate Keys - PyPI
|
|
130
125
|
```
|
131
126
|
---
|
132
127
|
|
133
|
-
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
128
|
+
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
134
129
|
_Set a new `name` and `value` for the JSON object_
|
135
130
|
- `name`: new key name for the JSON object. Supported flat key name format
|
136
131
|
- `value`: value for key `name`
|
132
|
+
- `case_insensitive`: the key name case (in)sensitive
|
137
133
|
- `separator`:
|
138
134
|
- `parse_index`:
|
139
135
|
- `dupSign_start`:
|
@@ -194,10 +190,11 @@ Description: # JSON Duplicate Keys - PyPI
|
|
194
190
|
```
|
195
191
|
---
|
196
192
|
|
197
|
-
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
193
|
+
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
198
194
|
_Update new `value` for existing `name` in the JSON object_
|
199
195
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
200
196
|
- `value`: new value for key `name`
|
197
|
+
- `case_insensitive`: the key name case (in)sensitive
|
201
198
|
- `separator`:
|
202
199
|
- `parse_index`:
|
203
200
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -219,9 +216,10 @@ Description: # JSON Duplicate Keys - PyPI
|
|
219
216
|
```
|
220
217
|
---
|
221
218
|
|
222
|
-
### JSON_DUPLICATE_KEYS.delete(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
219
|
+
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
223
220
|
_Delete a key-value pair in a JSON object by key `name`_
|
224
221
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
222
|
+
- `case_insensitive`: the key name case (in)sensitive
|
225
223
|
- `separator`:
|
226
224
|
- `parse_index`:
|
227
225
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -388,6 +386,12 @@ Description: # JSON Duplicate Keys - PyPI
|
|
388
386
|
---
|
389
387
|
|
390
388
|
## CHANGELOG
|
389
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.19)
|
390
|
+
- **Updated**: Allows getting (`JSON_DUPLICATE_KEYS.get`), setting (`JSON_DUPLICATE_KEYS.set`), updating (`JSON_DUPLICATE_KEYS.update`), deleting (`JSON_DUPLICATE_KEYS.delete`) JSON_DUPLICATE_KEYS objects with case-insensitive key names
|
391
|
+
|
392
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/truocphan/json-duplicate-keys/tree/2024.7.17)
|
393
|
+
- **Fixed**: issue [#3](https://github.com/truocphan/json-duplicate-keys/issues/3) break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
394
|
+
|
391
395
|
#### [json-duplicate-keys v2024.4.20](https://github.com/truocphan/json-duplicate-keys/tree/2024.4.20)
|
392
396
|
- **New**: _filter_values_
|
393
397
|
- **Updated**: _filter_keys_
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|