json-duplicate-keys 2024.7.17__py3-none-any.whl → 2024.11.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- json_duplicate_keys/__init__.py +140 -221
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.dist-info}/METADATA +12 -11
- json_duplicate_keys-2024.11.19.dist-info/RECORD +6 -0
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.dist-info}/WHEEL +1 -1
- json_duplicate_keys-2024.7.17.dist-info/RECORD +0 -6
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.dist-info}/LICENSE +0 -0
- {json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.dist-info}/top_level.txt +0 -0
json_duplicate_keys/__init__.py
CHANGED
@@ -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
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -7,18 +12,13 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
|
|
7
12
|
# User input data type validation
|
8
13
|
if type(_isDebug_) != bool: _isDebug_ = False
|
9
14
|
|
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)))
|
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
18
|
|
19
|
-
|
19
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
20
20
|
|
21
|
-
|
21
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
22
22
|
|
23
23
|
return re.sub('{dupSign_start}_\\d+_{dupSign_end}$'.format(dupSign_start=re.escape(dupSign_start), dupSign_end=re.escape(dupSign_end)), "", name)
|
24
24
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -38,18 +38,13 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
38
38
|
|
39
39
|
if type(ordered_dict) != bool: ordered_dict = False
|
40
40
|
|
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)))
|
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
|
49
44
|
|
50
|
-
|
45
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
51
46
|
|
52
|
-
|
47
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
53
48
|
|
54
49
|
def __convert_Jloads_to_Jobj(Jloads, Jobj):
|
55
50
|
if type(Jloads) in [dict, OrderedDict]:
|
@@ -141,8 +136,10 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
|
|
141
136
|
return JSON_DUPLICATE_KEYS(Jobj)
|
142
137
|
else:
|
143
138
|
if _isDebug_: print("\x1b[31m[-] DataError: Invalid JSON format\x1b[0m")
|
139
|
+
return False
|
144
140
|
except Exception as e:
|
145
141
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
142
|
+
return False
|
146
143
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
147
144
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
148
145
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -160,6 +157,7 @@ def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False,
|
|
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,71 @@ 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]
|
276
|
+
if re.search(re.escape(separator)+"$", name):
|
277
|
+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
278
|
+
return False
|
281
279
|
|
282
|
-
|
283
|
-
|
284
|
-
|
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
|
285
283
|
|
286
|
-
|
287
|
-
name = name_split_first||name_split_lastKey
|
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
|
284
|
+
Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)
|
315
285
|
|
316
|
-
|
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
|
317
292
|
|
318
|
-
|
319
|
-
for k in name_split:
|
320
|
-
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
321
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
322
|
-
else:
|
323
|
-
exec_expression += "["+repr(k)+"]"
|
293
|
+
exec_expression = "self.getObject()"
|
324
294
|
|
325
|
-
|
326
|
-
|
327
|
-
|
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()"
|
343
|
-
|
344
|
-
for k in name_split_first:
|
345
|
-
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
346
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
347
|
-
else:
|
348
|
-
exec_expression += "["+repr(k)+"]"
|
349
|
-
|
350
|
-
exec(exec_expression+".append({"+repr(name_split_lastKey)+":"+repr(value)+"})")
|
351
|
-
return True
|
352
|
-
elif type(self.get(separator.join(name_split_first), separator=separator, parse_index=parse_index)) == dict:
|
353
|
-
exec_expression = "self.getObject()"
|
354
|
-
|
355
|
-
for k in name_split_first:
|
356
|
-
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
357
|
-
exec_expression += "["+k.split(parse_index)[1]+"]"
|
358
|
-
else:
|
359
|
-
exec_expression += "["+repr(k)+"]"
|
360
|
-
|
361
|
-
exec(exec_expression+"["+repr(name_split_lastKey)+"]="+repr(value))
|
362
|
-
return True
|
363
|
-
else:
|
364
|
-
if _isDebug_: print("\x1b[31m[-] KeyNameNotExistError: {}\x1b[0m".format(separator.join(name_split_first)))
|
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]+"]"
|
365
298
|
else:
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
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
|
299
|
+
exec_expression += "["+repr(k)+"]"
|
300
|
+
|
301
|
+
exec(exec_expression+"="+repr(value))
|
302
|
+
return True
|
303
|
+
else:
|
304
|
+
if len(name.split(separator)) == 1:
|
305
|
+
self.getObject()[name] = value
|
383
306
|
return True
|
384
307
|
else:
|
385
|
-
if
|
386
|
-
|
387
|
-
|
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()"
|
388
311
|
|
389
|
-
|
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
|
390
323
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
391
324
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
392
325
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -395,30 +328,28 @@ class JSON_DUPLICATE_KEYS:
|
|
395
328
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
396
329
|
# # # # # # # # # # # # # # update # # # # # # # # # # # # # #
|
397
330
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
398
|
-
def update(self, name, value, separator="||", parse_index="$", _isDebug_=False):
|
331
|
+
def update(self, name, value, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
399
332
|
import re
|
400
333
|
|
401
334
|
# User input data type validation
|
402
335
|
if type(_isDebug_) != bool: _isDebug_ = False
|
403
336
|
|
404
|
-
|
405
|
-
if
|
406
|
-
|
407
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
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
|
408
340
|
|
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)))
|
341
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
412
342
|
|
413
|
-
|
343
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
414
344
|
|
415
|
-
|
345
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
416
346
|
|
417
|
-
if self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
|
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"]
|
418
349
|
try:
|
419
350
|
exec_expression = "self.getObject()"
|
420
351
|
|
421
|
-
for k in
|
352
|
+
for k in Jname.split(separator):
|
422
353
|
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
423
354
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
424
355
|
else:
|
@@ -438,30 +369,28 @@ class JSON_DUPLICATE_KEYS:
|
|
438
369
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
439
370
|
# # # # # # # # # # # # # # delete # # # # # # # # # # # # #
|
440
371
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
441
|
-
def delete(self, name, separator="||", parse_index="$", _isDebug_=False):
|
372
|
+
def delete(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
|
442
373
|
import re
|
443
374
|
|
444
375
|
# User input data type validation
|
445
376
|
if type(_isDebug_) != bool: _isDebug_ = False
|
446
377
|
|
447
|
-
|
448
|
-
if
|
449
|
-
|
450
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
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
|
451
381
|
|
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)))
|
382
|
+
if type(case_insensitive) != bool: case_insensitive = False
|
455
383
|
|
456
|
-
|
384
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
457
385
|
|
458
|
-
|
386
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
459
387
|
|
460
|
-
if self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
|
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"]
|
461
390
|
try:
|
462
391
|
exec_expression = "del self.getObject()"
|
463
392
|
|
464
|
-
for k in
|
393
|
+
for k in Jname.split(separator):
|
465
394
|
if re.search("^"+re.escape(parse_index)+"\\d+"+re.escape(parse_index)+"$", k):
|
466
395
|
exec_expression += "["+k.split(parse_index)[1]+"]"
|
467
396
|
else:
|
@@ -491,10 +420,10 @@ class JSON_DUPLICATE_KEYS:
|
|
491
420
|
for k, v in JDKSObject.getObject().items():
|
492
421
|
if type(k) == str and type(name) == str:
|
493
422
|
if re.search(name, k):
|
494
|
-
newJDKSObject.set(k, v, separator="
|
423
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
495
424
|
else:
|
496
425
|
if name == k:
|
497
|
-
newJDKSObject.set(k, v, separator="
|
426
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
498
427
|
|
499
428
|
return newJDKSObject
|
500
429
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -515,10 +444,10 @@ class JSON_DUPLICATE_KEYS:
|
|
515
444
|
for k, v in JDKSObject.getObject().items():
|
516
445
|
if type(v) == str and type(value) == str:
|
517
446
|
if re.search(value, v):
|
518
|
-
newJDKSObject.set(k, v, separator="
|
447
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
519
448
|
else:
|
520
449
|
if value == v:
|
521
|
-
newJDKSObject.set(k, v, separator="
|
450
|
+
newJDKSObject.set(k, v, separator="!!"+separator+"!!", parse_index="!!"+parse_index+"!!", ordered_dict=ordered_dict)
|
522
451
|
|
523
452
|
return newJDKSObject
|
524
453
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -536,14 +465,9 @@ class JSON_DUPLICATE_KEYS:
|
|
536
465
|
# User input data type validation
|
537
466
|
if type(_isDebug_) != bool: _isDebug_ = False
|
538
467
|
|
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 = "{{{"
|
468
|
+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
|
545
469
|
|
546
|
-
|
470
|
+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
547
471
|
|
548
472
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
549
473
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
@@ -553,7 +477,7 @@ class JSON_DUPLICATE_KEYS:
|
|
553
477
|
|
554
478
|
dupSign_end_escape_regex = re.escape(json.dumps({dupSign_end:""})[2:-6])
|
555
479
|
|
556
|
-
return re.sub(
|
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))
|
557
481
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
558
482
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
559
483
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -571,6 +495,7 @@ class JSON_DUPLICATE_KEYS:
|
|
571
495
|
Jfile.close()
|
572
496
|
except Exception as e:
|
573
497
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
498
|
+
return False
|
574
499
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
575
500
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
576
501
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -587,18 +512,13 @@ class JSON_DUPLICATE_KEYS:
|
|
587
512
|
|
588
513
|
if type(ordered_dict) != bool: ordered_dict = False
|
589
514
|
|
590
|
-
|
591
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
515
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
592
516
|
|
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 = "$"
|
517
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
598
518
|
|
599
519
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
600
520
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
601
|
-
|
521
|
+
return False
|
602
522
|
|
603
523
|
if len(self.getObject()) > 0:
|
604
524
|
try:
|
@@ -633,8 +553,10 @@ class JSON_DUPLICATE_KEYS:
|
|
633
553
|
__convert_Jobj_to_Jflat(self.getObject())
|
634
554
|
|
635
555
|
self.__Jobj = Jflat
|
556
|
+
return True
|
636
557
|
except Exception as e:
|
637
558
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
559
|
+
return False
|
638
560
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
639
561
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
640
562
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -652,18 +574,13 @@ class JSON_DUPLICATE_KEYS:
|
|
652
574
|
|
653
575
|
if type(ordered_dict) != bool: ordered_dict = False
|
654
576
|
|
655
|
-
|
656
|
-
if type(separator) not in [str, unicode]: separator = "||"
|
577
|
+
if type(separator) not in [str, unicode]: separator = "||"
|
657
578
|
|
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 = "$"
|
579
|
+
if type(parse_index) not in [str, unicode]: parse_index = "$"
|
663
580
|
|
664
581
|
if type(self.getObject()) not in [dict, OrderedDict]:
|
665
582
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
666
|
-
|
583
|
+
return False
|
667
584
|
|
668
585
|
if len(self.getObject()) > 0:
|
669
586
|
try:
|
@@ -688,8 +605,10 @@ class JSON_DUPLICATE_KEYS:
|
|
688
605
|
Jtmp = Jtmp[Jkey]
|
689
606
|
|
690
607
|
self.__Jobj = Jobj
|
608
|
+
return True
|
691
609
|
except Exception as e:
|
692
610
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
611
|
+
return False
|
693
612
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
694
613
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
695
614
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
{json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.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.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
|
@@ -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,10 +197,11 @@ print(JDKSObject.getObject())
|
|
201
197
|
```
|
202
198
|
---
|
203
199
|
|
204
|
-
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
200
|
+
### JSON_DUPLICATE_KEYS.update(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
205
201
|
_Update new `value` for existing `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
|
208
205
|
- `separator`:
|
209
206
|
- `parse_index`:
|
210
207
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -226,9 +223,10 @@ print(JDKSObject.getObject())
|
|
226
223
|
```
|
227
224
|
---
|
228
225
|
|
229
|
-
### JSON_DUPLICATE_KEYS.delete(`name`, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
226
|
+
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
230
227
|
_Delete a key-value pair in a JSON object by key `name`_
|
231
228
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
229
|
+
- `case_insensitive`: the key name case (in)sensitive
|
232
230
|
- `separator`:
|
233
231
|
- `parse_index`:
|
234
232
|
- `_isDebug_`: Show/ Hide debug error messages
|
@@ -395,6 +393,9 @@ print(JDKSObject.getObject())
|
|
395
393
|
---
|
396
394
|
|
397
395
|
## CHANGELOG
|
396
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.19)
|
397
|
+
- **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
|
398
|
+
|
398
399
|
#### [json-duplicate-keys v2024.7.17](https://github.com/truocphan/json-duplicate-keys/tree/2024.7.17)
|
399
400
|
- **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
401
|
|
@@ -0,0 +1,6 @@
|
|
1
|
+
json_duplicate_keys/__init__.py,sha256=K9bg6uSaRnP4JNorn0Y_Chw_ZnRIZoIU0RGxqHFk8-s,26545
|
2
|
+
json_duplicate_keys-2024.11.19.dist-info/LICENSE,sha256=_hudSGMciUc27wGR8EMKfeb3atJRlf6rbhJtLnel-nc,1093
|
3
|
+
json_duplicate_keys-2024.11.19.dist-info/METADATA,sha256=yAQnSyE3h__xXLTnBIbtQfLBEgeCC7eoZSFtG4vdVGE,18084
|
4
|
+
json_duplicate_keys-2024.11.19.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
5
|
+
json_duplicate_keys-2024.11.19.dist-info/top_level.txt,sha256=vdsGrPLVS_l-BFL1i4hCJBY5_-gq4Cwp-11yegA750Y,20
|
6
|
+
json_duplicate_keys-2024.11.19.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=FimszL_5d3l_ISHCIwt1y7mCsyo9In_XWpkvmTdt2Go,18518
|
4
|
-
json_duplicate_keys-2024.7.17.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,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.19.dist-info}/LICENSE
RENAMED
File without changes
|
{json_duplicate_keys-2024.7.17.dist-info → json_duplicate_keys-2024.11.19.dist-info}/top_level.txt
RENAMED
File without changes
|