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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: json-duplicate-keys
3
- Version: 2024.4.20
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_
@@ -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
- return re.sub('{dupSign_start}_\d+_{dupSign_end}$'.format(dupSign_start=re.escape(dupSign_start), dupSign_end=re.escape(dupSign_end)), "", name)
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
- try:
37
- if type(Jstr) not in [str, unicode]:
38
- exit("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
39
- if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
40
- if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
41
- except Exception as e:
42
- if type(Jstr) not in [str]:
43
- exit("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
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+"_\d+_"+dupSign_end_escape_regex+"$", k)[0]
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+"_\d+_"+dupSign_end_escape_regex+"$", i)[0]])
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(self.getObject()) in [list, dict, OrderedDict]:
204
- try:
205
- Jobj = self.__Jobj
206
- Jval = "JSON_DUPLICATE_KEYS_ERROR"
207
- name_split = name.split(separator)
208
-
209
- for i in range(len(name_split)):
210
- if type(Jobj) in [dict, OrderedDict] and name_split[i] in Jobj.keys():
211
- Jval = Jobj[name_split[i]]
212
- Jobj = Jobj[name_split[i]]
213
- elif type(Jobj) in [list] and re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", name_split[i]):
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
- try:
242
- if type(name) not in [str, unicode]:
243
- exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
244
- if type(separator) not in [str, unicode]: separator = "||"
245
- if type(parse_index) not in [str, unicode]: parse_index = "$"
246
- if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
247
- if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
248
- except Exception as e:
249
- if type(name) not in [str]:
250
- exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
251
- if type(separator) not in [str]: separator = "||"
252
- if type(parse_index) not in [str]: parse_index = "$"
253
- if type(dupSign_start) not in [str]: dupSign_start = "{{{"
254
- if type(dupSign_end) not in [str]: dupSign_end = "}}}"
255
-
256
- if type(self.getObject()) in [list, dict, OrderedDict]:
257
- try:
258
- name_split = name.split(separator)
259
- name_split_first = name_split[:-1]
260
- name_split_lastKey = name_split[-1]
261
-
262
- if not re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", name_split_lastKey):
263
- """
264
- name = name_split_first||name_split_lastKey
265
-
266
- if "name" exist in "self.getObject()"
267
- => Add duplicate key
268
- else if "name_split_first" exist in "self.getObject()"
269
- if typeof "name_split_first" is list
270
- if length of "name_split_lastKey" is 0
271
- => Add new key (append "value" to "name_split_first")
272
- else
273
- => Add new key (append dict "name_split_lastKey"/"value" to "name_split_first")
274
- else if typeof "name_split_first" is dict
275
- => Add new key ( name_split_first[name_split_lastKey] = value )
276
- else if length of "name_split_first" is 0 => Add new key
277
- if typeof self.getObject() is list
278
- if length of "name_split_lastKey" is 0
279
- => Add new key (append "value" to self.__Jobj)
280
- else
281
- => Add new key (append dict "name_split_lastKey"/"value" to self.__Jobj)
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
- if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: The key name does not end with the list index\x1b[0m")
355
- except Exception as e:
356
- if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
299
+ exec_expression += "["+repr(k)+"]"
300
+
301
+ exec(exec_expression+"="+repr(value))
302
+ return True
357
303
  else:
358
- if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
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
- return False
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 self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
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 name.split(separator):
390
- if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
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
- try:
416
- if type(name) not in [str, unicode]:
417
- exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
418
- if type(separator) not in [str, unicode]: separator = "||"
419
- if type(parse_index) not in [str, unicode]: parse_index = "$"
420
- except Exception as e:
421
- if type(name) not in [str]:
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 self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
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 name.split(separator):
431
- if re.search("^"+re.escape(parse_index)+"\d+"+re.escape(parse_index)+"$", k):
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="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
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="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
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="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
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="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
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(self.getObject()) in [list, dict, OrderedDict]:
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
- dupSign_end_escape_regex = re.escape(json.dumps({dupSign_end:""})[2:-6])
470
+ if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
515
471
 
516
- return re.sub(r'{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))
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
- __convert_Jobj_to_Jflat(self.getObject())
515
+ if type(separator) not in [str, unicode]: separator = "||"
590
516
 
591
- self.__Jobj = Jflat
592
- except Exception as e:
593
- if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
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(self.getObject()) in [dict, OrderedDict]:
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
- for k, v in self.__Jobj.items():
624
- Jtmp = Jobj
625
- Jkeys = k.split(separator)
579
+ if type(parse_index) not in [str, unicode]: parse_index = "$"
626
580
 
627
- for count, (Jkey, next_Jkeys) in enumerate(zip(Jkeys, Jkeys[1:] + [v]), 1):
628
- 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()
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
- if type(Jtmp) == list:
631
- Jkey = int(re.compile(re.escape(parse_index)+"(\d+)"+re.escape(parse_index)).match(Jkey).group(1))
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
- while Jkey >= len(Jtmp):
634
- Jtmp.append(v)
589
+ for k, v in self.__Jobj.items():
590
+ Jtmp = Jobj
591
+ Jkeys = k.split(separator)
635
592
 
636
- elif Jkey not in Jtmp:
637
- Jtmp[Jkey] = v
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
- Jtmp = Jtmp[Jkey]
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
- self.__Jobj = Jobj
642
- except Exception as e:
643
- if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
644
- else:
645
- if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
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.4.20
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_
@@ -2,7 +2,7 @@ import setuptools
2
2
 
3
3
  setuptools.setup(
4
4
  name="json-duplicate-keys",
5
- version="2024.4.20",
5
+ version="2024.11.19",
6
6
  author="TP Cyber Security",
7
7
  license="MIT",
8
8
  author_email="tpcybersec2023@gmail.com",