json-duplicate-keys 2024.7.17__py2-none-any.whl → 2024.11.28__py2-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- json_duplicate_keys/__init__.py +140 -212
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/METADATA +22 -14
- json_duplicate_keys-2024.11.28.dist-info/RECORD +6 -0
- json_duplicate_keys-2024.7.17.dist-info/RECORD +0 -6
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/LICENSE +0 -0
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/WHEEL +0 -0
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/top_level.txt +0 -0
json_duplicate_keys/__init__.py
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
try:
|
3
|
+
unicode # Python 2
|
4
|
+
except NameError:
|
5
|
+
unicode = str # Python 3
|
6
|
+
|
1
7
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
2
8
|
# # # # # # # # # # # Normalize Key name # # # # # # # # # # #
|
3
9
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -7,18 +13,13 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
|
|
7
13
|
# User input data type validation
|
8
14
|
if type(_isDebug_) != bool: _isDebug_ = False
|
9
15
|
|
10
|
-
|
11
|
-
if
|
12
|
-
|
13
|
-
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
14
|
-
|
15
|
-
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
16
|
-
except Exception as e:
|
17
|
-
if type(name) not in [str]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
16
|
+
if type(name) not in [str, unicode]:
|
17
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
18
|
+
return False
|
18
19
|
|
19
|
-
|
20
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
20
21
|
|
21
|
-
|
22
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
22
23
|
|
23
24
|
return re.sub('{dupSign_start}_\\d+_{dupSign_end}$'.format(dupSign_start=re.escape(dupSign_start), dupSign_end=re.escape(dupSign_end)), "", name)
|
24
25
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -38,18 +39,13 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
38
39
|
|
39
40
|
if type(ordered_dict) != bool: ordered_dict = False
|
40
41
|
|
41
|
-
|
42
|
-
if
|
43
|
-
|
44
|
-
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
45
|
-
|
46
|
-
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
47
|
-
except Exception as e:
|
48
|
-
if type(Jstr) not in [str]: exit("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
|
42
|
+
if type(Jstr) not in [str, unicode]:
|
43
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
|
44
|
+
return False
|
49
45
|
|
50
|
-
|
46
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
51
47
|
|
52
|
-
|
48
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
53
49
|
|
54
50
|
def __convert_Jloads_to_Jobj(Jloads, Jobj):
|
55
51
|
if type(Jloads) in [dict, OrderedDict]:
|
@@ -141,8 +137,10 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
141
137
|
return JSON_DUPLICATE_KEYS(Jobj)
|
142
138
|
else:
|
143
139
|
if _isDebug_: print("\x1b[31m[-] DataError: Invalid JSON format\x1b[0m")
|
140
|
+
return False
|
144
141
|
except Exception as e:
|
145
142
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
143
|
+
return False
|
146
144
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
147
145
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
148
146
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -153,13 +151,13 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
153
151
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
154
152
|
def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
|
155
153
|
try:
|
156
|
-
|
157
|
-
|
158
|
-
Jfile.close()
|
154
|
+
with open(Jfilepath) as Jfile:
|
155
|
+
Jstr = Jfile.read()
|
159
156
|
|
160
157
|
return loads(Jstr, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, _isDebug_=_isDebug_)
|
161
158
|
except Exception as e:
|
162
159
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
160
|
+
return False
|
163
161
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
164
162
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
165
163
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -189,49 +187,57 @@ class JSON_DUPLICATE_KEYS:
|
|
189
187
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
190
188
|
# # # # # # # # # # # # # # # get # # # # # # # # # # # # # # #
|
191
189
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
192
|
-
def get(self, name, separator="||", parse_index="$", _isDebug_=False):
|
190
|
+
def get(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
193
191
|
import re
|
194
192
|
from collections import OrderedDict
|
195
193
|
|
196
194
|
# User input data type validation
|
197
195
|
if type(_isDebug_) != bool: _isDebug_ = False
|
198
196
|
|
199
|
-
|
200
|
-
if
|
201
|
-
|
202
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
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"}
|
203
200
|
|
204
|
-
|
205
|
-
except Exception as e:
|
206
|
-
if type(name) not in [str]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
201
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
207
202
|
|
208
|
-
|
203
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
209
204
|
|
210
|
-
|
205
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
211
206
|
|
212
207
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
213
208
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
214
|
-
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
|
215
230
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
for i in range(len(name_split)):
|
222
|
-
if type(Jobj) in [dict, OrderedDict] and name_split[i] in Jobj.keys():
|
223
|
-
Jval = Jobj[name_split[i]]
|
224
|
-
Jobj = Jobj[name_split[i]]
|
225
|
-
elif type(Jobj) in [list] and re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", name_split[i]):
|
226
|
-
Jval = Jobj[int(name_split[i].split(parse_index)[1])]
|
227
|
-
Jobj = Jobj[int(name_split[i].split(parse_index)[1])]
|
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])]
|
228
235
|
else:
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
return "JSON_DUPLICATE_KEYS_ERROR"
|
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"}
|
235
241
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
236
242
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
237
243
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -240,7 +246,7 @@ class JSON_DUPLICATE_KEYS:
|
|
240
246
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
241
247
|
# # # # # # # # # # # # # # # set # # # # # # # # # # # # # # #
|
242
248
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
243
|
-
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):
|
244
250
|
import re
|
245
251
|
from collections import OrderedDict
|
246
252
|
|
@@ -249,144 +255,75 @@ class JSON_DUPLICATE_KEYS:
|
|
249
255
|
|
250
256
|
if type(ordered_dict) != bool: ordered_dict = False
|
251
257
|
|
252
|
-
|
253
|
-
if
|
254
|
-
|
255
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
256
|
-
|
257
|
-
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
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
|
258
261
|
|
259
|
-
|
262
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
260
263
|
|
261
|
-
|
262
|
-
except Exception as e:
|
263
|
-
if type(name) not in [str]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
264
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
264
265
|
|
265
|
-
|
266
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
266
267
|
|
267
|
-
|
268
|
-
|
269
|
-
if type(dupSign_start) not in [str]: dupSign_start = "{{{"
|
268
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
270
269
|
|
271
|
-
|
270
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
272
271
|
|
273
272
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
274
273
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
275
274
|
return False
|
276
275
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
name_split_lastKey = name_split[-1]
|
281
|
-
|
282
|
-
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", name_split_lastKey):
|
283
|
-
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: The key name does not end with the list index\x1b[0m")
|
284
|
-
return False
|
276
|
+
if re.search(re.escape(separator)+"$", name):
|
277
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
278
|
+
return False
|
285
279
|
|
286
|
-
|
287
|
-
name
|
288
|
-
|
289
|
-
if "name" exist in "self.getObject()"
|
290
|
-
=> Add duplicate key
|
291
|
-
else if "name_split_first" exist in "self.getObject()"
|
292
|
-
if typeof "name_split_first" is list
|
293
|
-
if length of "name_split_lastKey" is 0
|
294
|
-
=> Add new key (append "value" to "name_split_first")
|
295
|
-
else
|
296
|
-
=> Add new key (append dict "name_split_lastKey"/"value" to "name_split_first")
|
297
|
-
else if typeof "name_split_first" is dict
|
298
|
-
=> Add new key ( name_split_first[name_split_lastKey] = value )
|
299
|
-
else if length of "name_split_first" is 0 => Add new key
|
300
|
-
if typeof self.getObject() is list
|
301
|
-
if length of "name_split_lastKey" is 0
|
302
|
-
=> Add new key (append "value" to self.__Jobj)
|
303
|
-
else
|
304
|
-
=> Add new key (append dict "name_split_lastKey"/"value" to self.__Jobj)
|
305
|
-
else if typeof self.getObject() is dict
|
306
|
-
=> Add new key ( self.__Jobj[name_split_lastKey] = value )
|
307
|
-
"""
|
308
|
-
# Add duplicate key
|
309
|
-
if self.get(separator.join(name_split), separator=separator, parse_index=parse_index) != "JSON_DUPLICATE_KEYS_ERROR":
|
310
|
-
index = 2
|
311
|
-
while True:
|
312
|
-
if self.get(separator.join(name_split)+dupSign_start+"_"+str(index)+"_"+dupSign_end, separator=separator, parse_index=parse_index) == "JSON_DUPLICATE_KEYS_ERROR":
|
313
|
-
break
|
314
|
-
index += 1
|
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
|
315
283
|
|
316
|
-
|
284
|
+
Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)
|
317
285
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
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
|
324
292
|
|
325
|
-
|
326
|
-
return True
|
327
|
-
# Add new key
|
328
|
-
elif self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index) != "JSON_DUPLICATE_KEYS_ERROR":
|
329
|
-
if len(name_split_first) > 0:
|
330
|
-
if type(self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index)) == list:
|
331
|
-
if name_split_lastKey == "":
|
332
|
-
exec_expression = "self.getObject()"
|
333
|
-
|
334
|
-
for k in name_split_first:
|
335
|
-
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
336
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
337
|
-
else:
|
338
|
-
exec_expression += "["+repr(k)+"]"
|
339
|
-
|
340
|
-
exec(exec_expression+".append("+repr(value)+")")
|
341
|
-
else:
|
342
|
-
exec_expression = "self.getObject()"
|
293
|
+
exec_expression = "self.getObject()"
|
343
294
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
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]+"]"
|
298
|
+
else:
|
299
|
+
exec_expression += "["+repr(k)+"]"
|
349
300
|
|
350
|
-
|
351
|
-
|
352
|
-
|
301
|
+
exec(exec_expression+"="+repr(value))
|
302
|
+
return True
|
303
|
+
else:
|
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
|
+
if type(Jget["value"]) in [dict, OrderedDict]:
|
353
311
|
exec_expression = "self.getObject()"
|
354
312
|
|
355
|
-
for k in
|
313
|
+
for k in Jget["name"].split(separator)+[name.split(separator)[-1]]:
|
356
314
|
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
357
315
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
358
316
|
else:
|
359
317
|
exec_expression += "["+repr(k)+"]"
|
360
318
|
|
361
|
-
exec(exec_expression+"
|
319
|
+
exec(exec_expression+"="+repr(value))
|
362
320
|
return True
|
363
321
|
else:
|
364
|
-
if _isDebug_: print("\x1b[31m[-]
|
322
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
323
|
+
return False
|
365
324
|
else:
|
366
|
-
if
|
367
|
-
|
368
|
-
self.__Jobj.append(value)
|
369
|
-
else:
|
370
|
-
self.__Jobj.append({name_split_lastKey: value})
|
371
|
-
else:
|
372
|
-
self.__Jobj[name_split_lastKey] = value
|
373
|
-
return True
|
374
|
-
# Add new key
|
375
|
-
elif len(name_split_first) == 0:
|
376
|
-
if type(self.getObject()) == list:
|
377
|
-
if name_split_lastKey == "":
|
378
|
-
self.__Jobj.append(value)
|
379
|
-
else:
|
380
|
-
self.__Jobj.append({name_split_lastKey: value})
|
381
|
-
else:
|
382
|
-
self.__Jobj[name_split_lastKey] = value
|
383
|
-
return True
|
384
|
-
else:
|
385
|
-
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: {}\x1b[0m".format(separator.join(name_split_first)))
|
386
|
-
except Exception as e:
|
387
|
-
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
388
|
-
|
389
|
-
return False
|
325
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameNotExistError: {}\x1b[0m".format(separator.join(Jget["name"].split(separator)[:-1])))
|
326
|
+
return False
|
390
327
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
391
328
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
392
329
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -395,30 +332,31 @@ class JSON_DUPLICATE_KEYS:
|
|
395
332
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
396
333
|
# # # # # # # # # # # # # # update # # # # # # # # # # # # # #
|
397
334
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
398
|
-
def update(self, name, value, separator="||", parse_index="$", _isDebug_=False):
|
335
|
+
def update(self, name, value, case_insensitive=False, allow_new_key=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
|
399
336
|
import re
|
400
337
|
|
401
338
|
# User input data type validation
|
402
339
|
if type(_isDebug_) != bool: _isDebug_ = False
|
403
340
|
|
404
|
-
|
405
|
-
if
|
341
|
+
if type(name) not in [str, unicode]:
|
342
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
343
|
+
return False
|
406
344
|
|
407
|
-
|
345
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
408
346
|
|
409
|
-
|
410
|
-
except Exception as e:
|
411
|
-
if type(name) not in [str]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
347
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
412
348
|
|
413
|
-
|
349
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
414
350
|
|
415
|
-
|
351
|
+
_debug_ = _isDebug_
|
352
|
+
if allow_new_key: _debug_ = False
|
416
353
|
|
417
|
-
if self.get(name, separator=separator, parse_index=parse_index, _isDebug_=
|
354
|
+
if self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_debug_)["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
355
|
+
Jname = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["name"]
|
418
356
|
try:
|
419
357
|
exec_expression = "self.getObject()"
|
420
358
|
|
421
|
-
for k in
|
359
|
+
for k in Jname.split(separator):
|
422
360
|
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
423
361
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
424
362
|
else:
|
@@ -428,6 +366,8 @@ class JSON_DUPLICATE_KEYS:
|
|
428
366
|
return True
|
429
367
|
except Exception as e:
|
430
368
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
369
|
+
elif allow_new_key:
|
370
|
+
return self.set(name, value, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, _isDebug_=_isDebug_)
|
431
371
|
|
432
372
|
return False
|
433
373
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -438,30 +378,28 @@ class JSON_DUPLICATE_KEYS:
|
|
438
378
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
439
379
|
# # # # # # # # # # # # # # delete # # # # # # # # # # # # #
|
440
380
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
441
|
-
def delete(self, name, separator="||", parse_index="$", _isDebug_=False):
|
381
|
+
def delete(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
442
382
|
import re
|
443
383
|
|
444
384
|
# User input data type validation
|
445
385
|
if type(_isDebug_) != bool: _isDebug_ = False
|
446
386
|
|
447
|
-
|
448
|
-
if
|
449
|
-
|
450
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
387
|
+
if type(name) not in [str, unicode]:
|
388
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
389
|
+
return False
|
451
390
|
|
452
|
-
|
453
|
-
except Exception as e:
|
454
|
-
if type(name) not in [str]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
|
391
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
455
392
|
|
456
|
-
|
393
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
457
394
|
|
458
|
-
|
395
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
459
396
|
|
460
|
-
if self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
|
397
|
+
if self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_)["value"] != "JSON_DUPLICATE_KEYS_ERROR":
|
398
|
+
Jname = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)["name"]
|
461
399
|
try:
|
462
400
|
exec_expression = "del self.getObject()"
|
463
401
|
|
464
|
-
for k in
|
402
|
+
for k in Jname.split(separator):
|
465
403
|
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
466
404
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
467
405
|
else:
|
@@ -536,14 +474,9 @@ class JSON_DUPLICATE_KEYS:
|
|
536
474
|
# User input data type validation
|
537
475
|
if type(_isDebug_) != bool: _isDebug_ = False
|
538
476
|
|
539
|
-
|
540
|
-
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
541
|
-
|
542
|
-
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
543
|
-
except Exception as e:
|
544
|
-
if type(dupSign_start) not in [str]: dupSign_start = "{{{"
|
477
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
545
478
|
|
546
|
-
|
479
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
547
480
|
|
548
481
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
549
482
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
@@ -553,7 +486,7 @@ class JSON_DUPLICATE_KEYS:
|
|
553
486
|
|
554
487
|
dupSign_end_escape_regex = re.escape(json.dumps({dupSign_end:""})[2:-6])
|
555
488
|
|
556
|
-
return re.sub(
|
489
|
+
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))
|
557
490
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
558
491
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
559
492
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -571,6 +504,7 @@ class JSON_DUPLICATE_KEYS:
|
|
571
504
|
Jfile.close()
|
572
505
|
except Exception as e:
|
573
506
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
507
|
+
return False
|
574
508
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
575
509
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
576
510
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -587,18 +521,13 @@ class JSON_DUPLICATE_KEYS:
|
|
587
521
|
|
588
522
|
if type(ordered_dict) != bool: ordered_dict = False
|
589
523
|
|
590
|
-
|
591
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
524
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
592
525
|
|
593
|
-
|
594
|
-
except Exception as e:
|
595
|
-
if type(separator) not in [str]: separator = "||"
|
596
|
-
|
597
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
526
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
598
527
|
|
599
528
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
600
529
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
601
|
-
|
530
|
+
return False
|
602
531
|
|
603
532
|
if len(self.getObject()) > 0:
|
604
533
|
try:
|
@@ -633,8 +562,10 @@ class JSON_DUPLICATE_KEYS:
|
|
633
562
|
__convert_Jobj_to_Jflat(self.getObject())
|
634
563
|
|
635
564
|
self.__Jobj = Jflat
|
565
|
+
return True
|
636
566
|
except Exception as e:
|
637
567
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
568
|
+
return False
|
638
569
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
639
570
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
640
571
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -652,18 +583,13 @@ class JSON_DUPLICATE_KEYS:
|
|
652
583
|
|
653
584
|
if type(ordered_dict) != bool: ordered_dict = False
|
654
585
|
|
655
|
-
|
656
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
586
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
657
587
|
|
658
|
-
|
659
|
-
except Exception as e:
|
660
|
-
if type(separator) not in [str]: separator = "||"
|
661
|
-
|
662
|
-
if type(parse_index) not in [str]: parse_index = "$"
|
588
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
663
589
|
|
664
590
|
if type(self.getObject()) not in [dict, OrderedDict]:
|
665
591
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
666
|
-
|
592
|
+
return False
|
667
593
|
|
668
594
|
if len(self.getObject()) > 0:
|
669
595
|
try:
|
@@ -688,8 +614,10 @@ class JSON_DUPLICATE_KEYS:
|
|
688
614
|
Jtmp = Jtmp[Jkey]
|
689
615
|
|
690
616
|
self.__Jobj = Jobj
|
617
|
+
return True
|
691
618
|
except Exception as e:
|
692
619
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
620
|
+
return False
|
693
621
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
694
622
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
695
623
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
{json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.11.28
|
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
|
@@ -23,12 +23,6 @@ Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
|
23
23
|
<a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
|
24
24
|
<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>
|
25
25
|
<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>
|
26
|
-
<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>
|
27
|
-
<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>
|
28
|
-
<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>
|
29
|
-
<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>
|
30
|
-
<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>
|
31
|
-
<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>
|
32
26
|
</p>
|
33
27
|
|
34
28
|
## Installation
|
@@ -113,9 +107,10 @@ print(JDKSObject.getObject())
|
|
113
107
|
```
|
114
108
|
---
|
115
109
|
|
116
|
-
### JSON_DUPLICATE_KEYS.get(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
110
|
+
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
117
111
|
_Get value in the JSON object by `name`_
|
118
112
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
113
|
+
- `case_insensitive`: the key name case (in)sensitive
|
119
114
|
- `separator`:
|
120
115
|
- `parse_index`:
|
121
116
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -137,10 +132,11 @@ print(JDKSObject.get("snapshot||author"))
|
|
137
132
|
```
|
138
133
|
---
|
139
134
|
|
140
|
-
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
135
|
+
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
141
136
|
_Set a new `name` and `value` for the JSON object_
|
142
137
|
- `name`: new key name for the JSON object. Supported flat key name format
|
143
138
|
- `value`: value for key `name`
|
139
|
+
- `case_insensitive`: the key name case (in)sensitive
|
144
140
|
- `separator`:
|
145
141
|
- `parse_index`:
|
146
142
|
- `dupSign_start`:
|
@@ -201,12 +197,17 @@ print(JDKSObject.getObject())
|
|
201
197
|
```
|
202
198
|
---
|
203
199
|
|
204
|
-
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
205
|
-
_Update new `value` for existing `name` in the JSON object_
|
200
|
+
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `case_insensitive`=False, `allow_new_key`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
201
|
+
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
|
206
202
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
207
203
|
- `value`: new value for key `name`
|
204
|
+
- `case_insensitive`: the key name case (in)sensitive
|
205
|
+
- `allow_new_key`: allows to create a new key name if the key name does not exist
|
208
206
|
- `separator`:
|
209
207
|
- `parse_index`:
|
208
|
+
- `dupSign_start`:
|
209
|
+
- `dupSign_end`:
|
210
|
+
- `ordered_dict`: preserves the order in which the Keys are inserted
|
210
211
|
- `_isDebug_`: Show/ Hide debug error messages
|
211
212
|
```python
|
212
213
|
import json_duplicate_keys as jdks
|
@@ -226,9 +227,10 @@ print(JDKSObject.getObject())
|
|
226
227
|
```
|
227
228
|
---
|
228
229
|
|
229
|
-
### JSON_DUPLICATE_KEYS.delete(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
230
|
+
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
230
231
|
_Delete a key-value pair in a JSON object by key `name`_
|
231
232
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
233
|
+
- `case_insensitive`: the key name case (in)sensitive
|
232
234
|
- `separator`:
|
233
235
|
- `parse_index`:
|
234
236
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -256,7 +258,7 @@ print(JDKSObject.getObject())
|
|
256
258
|
- `name`:
|
257
259
|
- `separator`:
|
258
260
|
- `parse_index`:
|
259
|
-
- `ordered_dict`:
|
261
|
+
- `ordered_dict`: preserves the order in which the Keys are inserted
|
260
262
|
```python
|
261
263
|
import json_duplicate_keys as jdks
|
262
264
|
|
@@ -277,7 +279,7 @@ print(JDKSObject.dumps())
|
|
277
279
|
- `value`:
|
278
280
|
- `separator`:
|
279
281
|
- `parse_index`:
|
280
|
-
- `ordered_dict`:
|
282
|
+
- `ordered_dict`: preserves the order in which the Keys are inserted
|
281
283
|
```python
|
282
284
|
import json_duplicate_keys as jdks
|
283
285
|
|
@@ -395,6 +397,12 @@ print(JDKSObject.getObject())
|
|
395
397
|
---
|
396
398
|
|
397
399
|
## CHANGELOG
|
400
|
+
#### [json-duplicate-keys v2024.11.28](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.28)
|
401
|
+
- **Fixed**: Add subkey name to empty dict of existing key name
|
402
|
+
|
403
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.19)
|
404
|
+
- **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
|
405
|
+
|
398
406
|
#### [json-duplicate-keys v2024.7.17](https://github.com/truocphan/json-duplicate-keys/tree/2024.7.17)
|
399
407
|
- **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.
|
400
408
|
|
@@ -0,0 +1,6 @@
|
|
1
|
+
json_duplicate_keys/__init__.py,SHA256=YV3PpNeXAynBoY46yTs_M3t3KivpXvOLdeMD__IyviM,27170
|
2
|
+
json_duplicate_keys-2024.11.28.dist-info/LICENSE,SHA256=_hudSGMciUc27wGR8EMKfeb3atJRlf6rbhJtLnel-nc,1093
|
3
|
+
json_duplicate_keys-2024.11.28.dist-info/METADATA,SHA256=YsVbH-oTT_YslwHqdluw1470mrSvgg4iO50cNcKHPdk,18243
|
4
|
+
json_duplicate_keys-2024.11.28.dist-info/WHEEL,SHA256=1VPi6hfNQaRRNuEdK_3dv9o8COtLGnHWJghhj4CQ28k,92
|
5
|
+
json_duplicate_keys-2024.11.28.dist-info/top_level.txt,SHA256=vdsGrPLVS_l-BFL1i4hCJBY5_-gq4Cwp-11yegA750Y,20
|
6
|
+
json_duplicate_keys-2024.11.28.dist-info/RECORD,,
|
@@ -1,6 +0,0 @@
|
|
1
|
-
json_duplicate_keys/__init__.py,SHA256=5RW69Kmsa6cKAifXRzATwU5dBa-ulzVY9pBUEb7nRe0,29951
|
2
|
-
json_duplicate_keys-2024.7.17.dist-info/LICENSE,SHA256=_hudSGMciUc27wGR8EMKfeb3atJRlf6rbhJtLnel-nc,1093
|
3
|
-
json_duplicate_keys-2024.7.17.dist-info/METADATA,SHA256=NB-7fKagSVyf32CJpIGgVD2mksXOmtzv07wYC0dCfE4,18108
|
4
|
-
json_duplicate_keys-2024.7.17.dist-info/WHEEL,SHA256=1VPi6hfNQaRRNuEdK_3dv9o8COtLGnHWJghhj4CQ28k,92
|
5
|
-
json_duplicate_keys-2024.7.17.dist-info/top_level.txt,SHA256=vdsGrPLVS_l-BFL1i4hCJBY5_-gq4Cwp-11yegA750Y,20
|
6
|
-
json_duplicate_keys-2024.7.17.dist-info/RECORD,,
|
{json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
{json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.28.dist-info}/top_level.txt
RENAMED
File without changes
|