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