json-duplicate-keys 2024.7.17__py3-none-any.whl → 2024.11.28__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.
@@ -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
- try:
11
- if type(name) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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
- if type(dupSign_start) not in [str]: dupSign_start = "{{{"
20
+ if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
20
21
 
21
- if type(dupSign_end) not in [str]: dupSign_end = "}}}"
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
- try:
42
- if type(Jstr) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the JSON object must be str or unicode, not {}\x1b[0m".format(type(Jstr)))
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
- if type(dupSign_start) not in [str]: dupSign_start = "{{{"
46
+ if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
51
47
 
52
- if type(dupSign_end) not in [str]: dupSign_end = "}}}"
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
- Jfile = open(Jfilepath)
157
- Jstr = Jfile.read()
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
- try:
200
- if type(name) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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
- if type(parse_index) not in [str, unicode]: parse_index = "$"
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
- if type(separator) not in [str]: separator = "||"
203
+ if type(separator) not in [str, unicode]: separator = "||"
209
204
 
210
- if type(parse_index) not in [str]: parse_index = "$"
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
- try:
217
- Jobj = self.__Jobj
218
- Jval = "JSON_DUPLICATE_KEYS_ERROR"
219
- name_split = name.split(separator)
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
- if _isDebug_: print("\x1b[31m[-] KeyNotFoundError: \x1b[0m"+separator.join(name_split[:i+1]))
230
- return "JSON_DUPLICATE_KEYS_ERROR"
231
- return Jval
232
- except Exception as e:
233
- if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
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
- try:
253
- if type(name) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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
- if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
262
+ if type(case_insensitive) != bool: case_insensitive = False
260
263
 
261
- if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
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
- if type(separator) not in [str]: separator = "||"
266
+ if type(parse_index) not in [str, unicode]: parse_index = "$"
266
267
 
267
- if type(parse_index) not in [str]: parse_index = "$"
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
- if type(dupSign_end) not in [str]: dupSign_end = "}}}"
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
- try:
278
- name_split = name.split(separator)
279
- name_split_first = name_split[:-1]
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 = 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
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
- exec_expression = "self.getObject()"
284
+ Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index)
317
285
 
318
- name_split[-1] = name_split[-1]+dupSign_start+"_"+str(index)+"_"+dupSign_end
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)+"]"
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
- exec(exec_expression+"="+repr(value))
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
- 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)+"]"
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
- 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:
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 name_split_first:
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+"["+repr(name_split_lastKey)+"]="+repr(value))
319
+ exec(exec_expression+"="+repr(value))
362
320
  return True
363
321
  else:
364
- if _isDebug_: print("\x1b[31m[-] KeyNameNotExistError: {}\x1b[0m".format(separator.join(name_split_first)))
322
+ if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
323
+ return False
365
324
  else:
366
- if type(self.getObject()) == list:
367
- if name_split_lastKey == "":
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
- try:
405
- if type(name) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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
- if type(separator) not in [str, unicode]: separator = "||"
345
+ if type(case_insensitive) != bool: case_insensitive = False
408
346
 
409
- if type(parse_index) not in [str, unicode]: parse_index = "$"
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
- if type(separator) not in [str]: separator = "||"
349
+ if type(parse_index) not in [str, unicode]: parse_index = "$"
414
350
 
415
- if type(parse_index) not in [str]: parse_index = "$"
351
+ _debug_ = _isDebug_
352
+ if allow_new_key: _debug_ = False
416
353
 
417
- if self.get(name, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_) != "JSON_DUPLICATE_KEYS_ERROR":
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 name.split(separator):
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
- try:
448
- if type(name) not in [str, unicode]: exit("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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
- if type(parse_index) not in [str, unicode]: parse_index = "$"
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
- if type(separator) not in [str]: separator = "||"
393
+ if type(separator) not in [str, unicode]: separator = "||"
457
394
 
458
- if type(parse_index) not in [str]: parse_index = "$"
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 name.split(separator):
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
- try:
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
- if type(dupSign_end) not in [str]: dupSign_end = "}}}"
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(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))
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
- try:
591
- if type(separator) not in [str, unicode]: separator = "||"
524
+ if type(separator) not in [str, unicode]: separator = "||"
592
525
 
593
- if type(parse_index) not in [str, unicode]: parse_index = "$"
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
- exit()
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
- try:
656
- if type(separator) not in [str, unicode]: separator = "||"
586
+ if type(separator) not in [str, unicode]: separator = "||"
657
587
 
658
- if type(parse_index) not in [str, unicode]: parse_index = "$"
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
- exit()
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
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: json-duplicate-keys
3
- Version: 2024.7.17
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=zIHJT2JFMlMJHG7sBu-wk_O-PM6NvMwK6rweJKQUhuM,18661
4
+ json_duplicate_keys-2024.11.28.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,