json-duplicate-keys 2024.11.28__tar.gz → 2025.6.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: json-duplicate-keys
3
- Version: 2024.11.28
3
+ Version: 2025.6.6
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
@@ -17,12 +17,15 @@ License-File: LICENSE
17
17
  Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
18
18
 
19
19
  <p align="center">
20
- <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
20
+ <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
21
21
  <a href="#"><img src="https://img.shields.io/github/downloads/truocphan/json-duplicate-keys/total" height=30></a>
22
22
  <a href="#"><img src="https://img.shields.io/github/stars/truocphan/json-duplicate-keys" height=30></a>
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
+ <br>
27
+ <a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
28
+ <a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
26
29
  </p>
27
30
 
28
31
  ## Installation
@@ -53,12 +56,13 @@ print(jdks.normalize_key("version{{{_2_}}}"))
53
56
  ```
54
57
  ---
55
58
 
56
- ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
59
+ ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
57
60
  _Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
58
61
  - `Jstr`: a JSON format string
59
62
  - `dupSign_start`:
60
63
  - `dupSign_end`:
61
64
  - `ordered_dict`: preserves the order in which the Keys are inserted
65
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
62
66
  - `_isDebug_`: Show/ Hide debug error messages
63
67
  ```python
64
68
  import json_duplicate_keys as jdks
@@ -72,12 +76,13 @@ print(JDKSObject)
72
76
  ```
73
77
  ---
74
78
 
75
- ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
79
+ ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
76
80
  _Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
77
81
  - `Jfilepath`: The path to the file containing the JSON format string
78
82
  - `dupSign_start`:
79
83
  - `dupSign_end`:
80
84
  - `ordered_dict`: preserves the order in which the Keys are inserted
85
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
81
86
  - `_isDebug_`: Show/ Hide debug error messages
82
87
  ```python
83
88
  # /path/to/file.json: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
@@ -122,13 +127,13 @@ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "relea
122
127
  JDKSObject = jdks.loads(Jstr)
123
128
 
124
129
  print(JDKSObject.get("version{{{_2_}}}"))
125
- # OUTPUT: latest
130
+ # OUTPUT: {'name': 'version{{{_2_}}}', 'value': 'latest'}
126
131
 
127
132
  print(JDKSObject.get("release||$0$"))
128
- # OUTPUT: {'version': 'latest'}
133
+ # OUTPUT: {'name': 'release||$0$', 'value': {'version': 'latest'}}
129
134
 
130
135
  print(JDKSObject.get("snapshot||author"))
131
- # OUTPUT: truocphan
136
+ # OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
132
137
  ```
133
138
  ---
134
139
 
@@ -197,6 +202,35 @@ print(JDKSObject.getObject())
197
202
  ```
198
203
  ---
199
204
 
205
+ ### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
206
+ _Insert `value` at `position` in value list of `name`_
207
+ - `name`: the key name of the JSON object. Supported flatten key name format
208
+ - `value`: new value for key `name`
209
+ - `position`: position of the `value` to insert (default insert at the last position of the list)
210
+ - `case_insensitive`: the key name case (in)sensitive
211
+ - `separator`:
212
+ - `parse_index`:
213
+ - `dupSign_start`:
214
+ - `dupSign_end`:
215
+ - `_isDebug_`: Show/ Hide debug error messages
216
+ ```python
217
+ import json_duplicate_keys as jdks
218
+
219
+ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
220
+
221
+ JDKSObject = jdks.loads(Jstr)
222
+
223
+ print(JDKSObject.getObject())
224
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
225
+
226
+ JDKSObject.insert("release", {'version': '2025.1.1'})
227
+ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
228
+
229
+ print(JDKSObject.getObject())
230
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}, {'version': '2025.1.1'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': '2025.1.1'}, {'version': 'latest'}]}}
231
+ ```
232
+ ---
233
+
200
234
  ### 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
235
  _Update new `value` for existing `name` or Set a new `name` in the JSON object_
202
236
  - `name`: the key name of the JSON object. Supported flatten key name format
@@ -397,6 +431,12 @@ print(JDKSObject.getObject())
397
431
  ---
398
432
 
399
433
  ## CHANGELOG
434
+ #### [json-duplicate-keys v2025.6.6](https://github.com/truocphan/json-duplicate-keys/tree/2025.6.6)
435
+ - [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
436
+
437
+ #### [json-duplicate-keys v2024.12.12](https://github.com/truocphan/json-duplicate-keys/tree/2024.12.12)
438
+ - **New**: _insert_ function
439
+
400
440
  #### [json-duplicate-keys v2024.11.28](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.28)
401
441
  - **Fixed**: Add subkey name to empty dict of existing key name
402
442
 
@@ -2,12 +2,15 @@
2
2
  Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
3
3
 
4
4
  <p align="center">
5
- <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
5
+ <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
6
6
  <a href="#"><img src="https://img.shields.io/github/downloads/truocphan/json-duplicate-keys/total" height=30></a>
7
7
  <a href="#"><img src="https://img.shields.io/github/stars/truocphan/json-duplicate-keys" height=30></a>
8
8
  <a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
9
9
  <a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/truocphan/json-duplicate-keys" height=30></a>
10
10
  <a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/truocphan/json-duplicate-keys" height=30></a>
11
+ <br>
12
+ <a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
13
+ <a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
11
14
  </p>
12
15
 
13
16
  ## Installation
@@ -38,12 +41,13 @@ print(jdks.normalize_key("version{{{_2_}}}"))
38
41
  ```
39
42
  ---
40
43
 
41
- ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
44
+ ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
42
45
  _Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
43
46
  - `Jstr`: a JSON format string
44
47
  - `dupSign_start`:
45
48
  - `dupSign_end`:
46
49
  - `ordered_dict`: preserves the order in which the Keys are inserted
50
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
47
51
  - `_isDebug_`: Show/ Hide debug error messages
48
52
  ```python
49
53
  import json_duplicate_keys as jdks
@@ -57,12 +61,13 @@ print(JDKSObject)
57
61
  ```
58
62
  ---
59
63
 
60
- ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
64
+ ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
61
65
  _Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
62
66
  - `Jfilepath`: The path to the file containing the JSON format string
63
67
  - `dupSign_start`:
64
68
  - `dupSign_end`:
65
69
  - `ordered_dict`: preserves the order in which the Keys are inserted
70
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
66
71
  - `_isDebug_`: Show/ Hide debug error messages
67
72
  ```python
68
73
  # /path/to/file.json: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
@@ -107,13 +112,13 @@ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "relea
107
112
  JDKSObject = jdks.loads(Jstr)
108
113
 
109
114
  print(JDKSObject.get("version{{{_2_}}}"))
110
- # OUTPUT: latest
115
+ # OUTPUT: {'name': 'version{{{_2_}}}', 'value': 'latest'}
111
116
 
112
117
  print(JDKSObject.get("release||$0$"))
113
- # OUTPUT: {'version': 'latest'}
118
+ # OUTPUT: {'name': 'release||$0$', 'value': {'version': 'latest'}}
114
119
 
115
120
  print(JDKSObject.get("snapshot||author"))
116
- # OUTPUT: truocphan
121
+ # OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
117
122
  ```
118
123
  ---
119
124
 
@@ -182,6 +187,35 @@ print(JDKSObject.getObject())
182
187
  ```
183
188
  ---
184
189
 
190
+ ### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
191
+ _Insert `value` at `position` in value list of `name`_
192
+ - `name`: the key name of the JSON object. Supported flatten key name format
193
+ - `value`: new value for key `name`
194
+ - `position`: position of the `value` to insert (default insert at the last position of the list)
195
+ - `case_insensitive`: the key name case (in)sensitive
196
+ - `separator`:
197
+ - `parse_index`:
198
+ - `dupSign_start`:
199
+ - `dupSign_end`:
200
+ - `_isDebug_`: Show/ Hide debug error messages
201
+ ```python
202
+ import json_duplicate_keys as jdks
203
+
204
+ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
205
+
206
+ JDKSObject = jdks.loads(Jstr)
207
+
208
+ print(JDKSObject.getObject())
209
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
210
+
211
+ JDKSObject.insert("release", {'version': '2025.1.1'})
212
+ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
213
+
214
+ print(JDKSObject.getObject())
215
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}, {'version': '2025.1.1'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': '2025.1.1'}, {'version': 'latest'}]}}
216
+ ```
217
+ ---
218
+
185
219
  ### 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)
186
220
  _Update new `value` for existing `name` or Set a new `name` in the JSON object_
187
221
  - `name`: the key name of the JSON object. Supported flatten key name format
@@ -382,6 +416,12 @@ print(JDKSObject.getObject())
382
416
  ---
383
417
 
384
418
  ## CHANGELOG
419
+ #### [json-duplicate-keys v2025.6.6](https://github.com/truocphan/json-duplicate-keys/tree/2025.6.6)
420
+ - [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
421
+
422
+ #### [json-duplicate-keys v2024.12.12](https://github.com/truocphan/json-duplicate-keys/tree/2024.12.12)
423
+ - **New**: _insert_ function
424
+
385
425
  #### [json-duplicate-keys v2024.11.28](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.28)
386
426
  - **Fixed**: Add subkey name to empty dict of existing key name
387
427
 
@@ -1,15 +1,17 @@
1
1
  # -*- coding: utf-8 -*-
2
+ json_duplicate_keys_VERSION = "2025.6.6"
2
3
  try:
3
4
  unicode # Python 2
4
5
  except NameError:
5
6
  unicode = str # Python 3
6
7
 
8
+ from collections import OrderedDict
9
+ import json, re, copy
10
+
7
11
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
8
12
  # # # # # # # # # # # Normalize Key name # # # # # # # # # # #
9
13
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
10
14
  def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False):
11
- import re
12
-
13
15
  # User input data type validation
14
16
  if type(_isDebug_) != bool: _isDebug_ = False
15
17
 
@@ -30,10 +32,7 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
30
32
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
31
33
  # # # # # # # # # # # # # # # loads # # # # # # # # # # # # # #
32
34
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
33
- def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
34
- import json, re
35
- from collections import OrderedDict
36
-
35
+ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skipDuplicated=False, _isDebug_=False):
37
36
  # User input data type validation
38
37
  if type(_isDebug_) != bool: _isDebug_ = False
39
38
 
@@ -95,6 +94,9 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
95
94
  Jloads = json.loads(Jstr)
96
95
  if ordered_dict: Jloads = json.loads(Jstr, object_pairs_hook=OrderedDict)
97
96
 
97
+ if skipDuplicated:
98
+ return JSON_DUPLICATE_KEYS(Jloads)
99
+
98
100
  if type(Jloads) in [list, dict, OrderedDict]:
99
101
  dupSign_start_escape = "".join(["\\\\u"+hex(ord(c))[2:].zfill(4) for c in dupSign_start])
100
102
  dupSign_start_escape_regex = re.escape(dupSign_start)
@@ -149,12 +151,12 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isD
149
151
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
150
152
  # # # # # # # # # # # # # # # load # # # # # # # # # # # # # #
151
153
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
152
- def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
154
+ def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skipDuplicated=False, _isDebug_=False):
153
155
  try:
154
156
  with open(Jfilepath) as Jfile:
155
157
  Jstr = Jfile.read()
156
158
 
157
- return loads(Jstr, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, _isDebug_=_isDebug_)
159
+ return loads(Jstr, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, skipDuplicated=skipDuplicated, _isDebug_=_isDebug_)
158
160
  except Exception as e:
159
161
  if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
160
162
  return False
@@ -169,7 +171,6 @@ def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False,
169
171
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
170
172
  class JSON_DUPLICATE_KEYS:
171
173
  def __init__(self, Jobj):
172
- from collections import OrderedDict
173
174
  self.__Jobj = dict()
174
175
  if type(Jobj) in [dict, OrderedDict, list]:
175
176
  self.__Jobj = Jobj
@@ -188,9 +189,6 @@ class JSON_DUPLICATE_KEYS:
188
189
  # # # # # # # # # # # # # # # get # # # # # # # # # # # # # # #
189
190
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
190
191
  def get(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
191
- import re
192
- from collections import OrderedDict
193
-
194
192
  # User input data type validation
195
193
  if type(_isDebug_) != bool: _isDebug_ = False
196
194
 
@@ -247,9 +245,6 @@ class JSON_DUPLICATE_KEYS:
247
245
  # # # # # # # # # # # # # # # set # # # # # # # # # # # # # # #
248
246
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
249
247
  def set(self, name, value, case_insensitive=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
250
- import re
251
- from collections import OrderedDict
252
-
253
248
  # User input data type validation
254
249
  if type(_isDebug_) != bool: _isDebug_ = False
255
250
 
@@ -329,12 +324,55 @@ class JSON_DUPLICATE_KEYS:
329
324
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
330
325
 
331
326
 
327
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
328
+ # # # # # # # # # # # # # # insert # # # # # # # # # # # # # #
329
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
330
+ def insert(self, name, value, position=None, case_insensitive=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False):
331
+ # User input data type validation
332
+ if type(_isDebug_) != bool: _isDebug_ = False
333
+
334
+ if type(name) not in [str, unicode]:
335
+ if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
336
+ return False
337
+
338
+ if type(position) != int: position = None
339
+
340
+ if type(case_insensitive) != bool: case_insensitive = False
341
+
342
+ if type(separator) not in [str, unicode]: separator = "||"
343
+
344
+ if type(parse_index) not in [str, unicode]: parse_index = "$"
345
+
346
+ if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
347
+
348
+ if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
349
+
350
+ if type(self.getObject()) not in [list, dict, OrderedDict]:
351
+ if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
352
+ return False
353
+
354
+ if re.search(re.escape(separator)+"$", name):
355
+ if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
356
+ return False
357
+
358
+ Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_)
359
+
360
+ if Jget["value"] != "JSON_DUPLICATE_KEYS_ERROR":
361
+ if type(Jget["value"]) == list:
362
+ if position == None: position = len(Jget["value"])
363
+
364
+ Jget["value"].insert(position, value)
365
+
366
+ return self.update(Jget["name"], Jget["value"], separator=separator, parse_index=parse_index, dupSign_start=dupSign_start, dupSign_end=dupSign_end, _isDebug_=_isDebug_)
367
+ else:
368
+ if _isDebug_: print("\x1b[31m[-] DataTypeError: The data type of {} must be list, not {}\x1b[0m".format(Jget["name"], type(Jget["value"])))
369
+ return False
370
+
371
+
332
372
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
333
373
  # # # # # # # # # # # # # # update # # # # # # # # # # # # # #
334
374
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
335
375
  def update(self, name, value, case_insensitive=False, allow_new_key=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
336
- import re
337
-
338
376
  # User input data type validation
339
377
  if type(_isDebug_) != bool: _isDebug_ = False
340
378
 
@@ -379,8 +417,6 @@ class JSON_DUPLICATE_KEYS:
379
417
  # # # # # # # # # # # # # # delete # # # # # # # # # # # # #
380
418
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
381
419
  def delete(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
382
- import re
383
-
384
420
  # User input data type validation
385
421
  if type(_isDebug_) != bool: _isDebug_ = False
386
422
 
@@ -420,8 +456,6 @@ class JSON_DUPLICATE_KEYS:
420
456
  # # # # # # # # # # # # filter_keys # # # # # # # # # # # # #
421
457
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
422
458
  def filter_keys(self, name, separator="||", parse_index="$", ordered_dict=False):
423
- import re, copy
424
-
425
459
  JDKSObject = copy.deepcopy(self)
426
460
  JDKSObject.flatten(separator=separator, parse_index=parse_index, ordered_dict=ordered_dict)
427
461
  newJDKSObject = loads("{}", ordered_dict=ordered_dict)
@@ -444,8 +478,6 @@ class JSON_DUPLICATE_KEYS:
444
478
  # # # # # # # # # # # # filter_values # # # # # # # # # # # # #
445
479
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
446
480
  def filter_values(self, value, separator="||", parse_index="$", ordered_dict=False):
447
- import re, copy
448
-
449
481
  JDKSObject = copy.deepcopy(self)
450
482
  JDKSObject.flatten(separator=separator, parse_index=parse_index, ordered_dict=ordered_dict)
451
483
  newJDKSObject = loads("{}", ordered_dict=ordered_dict)
@@ -468,9 +500,6 @@ class JSON_DUPLICATE_KEYS:
468
500
  # # # # # # # # # # # # # # dumps # # # # # # # # # # # # # #
469
501
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
470
502
  def dumps(self, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False):
471
- import json, re
472
- from collections import OrderedDict
473
-
474
503
  # User input data type validation
475
504
  if type(_isDebug_) != bool: _isDebug_ = False
476
505
 
@@ -514,8 +543,6 @@ class JSON_DUPLICATE_KEYS:
514
543
  # # # # # # # # # # # # # flatten # # # # # # # # # # # # # #
515
544
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
516
545
  def flatten(self, separator="||", parse_index="$", ordered_dict=False, _isDebug_=False):
517
- from collections import OrderedDict
518
-
519
546
  # User input data type validation
520
547
  if type(_isDebug_) != bool: _isDebug_ = False
521
548
 
@@ -575,9 +602,6 @@ class JSON_DUPLICATE_KEYS:
575
602
  # # # # # # # # # # # # # unflatten # # # # # # # # # # # # #
576
603
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
577
604
  def unflatten(self, separator="||", parse_index="$", ordered_dict=False, _isDebug_=False):
578
- import re
579
- from collections import OrderedDict
580
-
581
605
  # User input data type validation
582
606
  if type(_isDebug_) != bool: _isDebug_ = False
583
607
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: json-duplicate-keys
3
- Version: 2024.11.28
3
+ Version: 2025.6.6
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
@@ -17,12 +17,15 @@ License-File: LICENSE
17
17
  Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
18
18
 
19
19
  <p align="center">
20
- <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
20
+ <a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
21
21
  <a href="#"><img src="https://img.shields.io/github/downloads/truocphan/json-duplicate-keys/total" height=30></a>
22
22
  <a href="#"><img src="https://img.shields.io/github/stars/truocphan/json-duplicate-keys" height=30></a>
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
+ <br>
27
+ <a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
28
+ <a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
26
29
  </p>
27
30
 
28
31
  ## Installation
@@ -53,12 +56,13 @@ print(jdks.normalize_key("version{{{_2_}}}"))
53
56
  ```
54
57
  ---
55
58
 
56
- ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
59
+ ### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
57
60
  _Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
58
61
  - `Jstr`: a JSON format string
59
62
  - `dupSign_start`:
60
63
  - `dupSign_end`:
61
64
  - `ordered_dict`: preserves the order in which the Keys are inserted
65
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
62
66
  - `_isDebug_`: Show/ Hide debug error messages
63
67
  ```python
64
68
  import json_duplicate_keys as jdks
@@ -72,12 +76,13 @@ print(JDKSObject)
72
76
  ```
73
77
  ---
74
78
 
75
- ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
79
+ ### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
76
80
  _Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
77
81
  - `Jfilepath`: The path to the file containing the JSON format string
78
82
  - `dupSign_start`:
79
83
  - `dupSign_end`:
80
84
  - `ordered_dict`: preserves the order in which the Keys are inserted
85
+ - `skipDuplicated`: Skip loading duplicate keys to improve execution performance
81
86
  - `_isDebug_`: Show/ Hide debug error messages
82
87
  ```python
83
88
  # /path/to/file.json: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
@@ -122,13 +127,13 @@ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "relea
122
127
  JDKSObject = jdks.loads(Jstr)
123
128
 
124
129
  print(JDKSObject.get("version{{{_2_}}}"))
125
- # OUTPUT: latest
130
+ # OUTPUT: {'name': 'version{{{_2_}}}', 'value': 'latest'}
126
131
 
127
132
  print(JDKSObject.get("release||$0$"))
128
- # OUTPUT: {'version': 'latest'}
133
+ # OUTPUT: {'name': 'release||$0$', 'value': {'version': 'latest'}}
129
134
 
130
135
  print(JDKSObject.get("snapshot||author"))
131
- # OUTPUT: truocphan
136
+ # OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
132
137
  ```
133
138
  ---
134
139
 
@@ -197,6 +202,35 @@ print(JDKSObject.getObject())
197
202
  ```
198
203
  ---
199
204
 
205
+ ### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
206
+ _Insert `value` at `position` in value list of `name`_
207
+ - `name`: the key name of the JSON object. Supported flatten key name format
208
+ - `value`: new value for key `name`
209
+ - `position`: position of the `value` to insert (default insert at the last position of the list)
210
+ - `case_insensitive`: the key name case (in)sensitive
211
+ - `separator`:
212
+ - `parse_index`:
213
+ - `dupSign_start`:
214
+ - `dupSign_end`:
215
+ - `_isDebug_`: Show/ Hide debug error messages
216
+ ```python
217
+ import json_duplicate_keys as jdks
218
+
219
+ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
220
+
221
+ JDKSObject = jdks.loads(Jstr)
222
+
223
+ print(JDKSObject.getObject())
224
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
225
+
226
+ JDKSObject.insert("release", {'version': '2025.1.1'})
227
+ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
228
+
229
+ print(JDKSObject.getObject())
230
+ # OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}, {'version': '2025.1.1'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': '2025.1.1'}, {'version': 'latest'}]}}
231
+ ```
232
+ ---
233
+
200
234
  ### 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
235
  _Update new `value` for existing `name` or Set a new `name` in the JSON object_
202
236
  - `name`: the key name of the JSON object. Supported flatten key name format
@@ -397,6 +431,12 @@ print(JDKSObject.getObject())
397
431
  ---
398
432
 
399
433
  ## CHANGELOG
434
+ #### [json-duplicate-keys v2025.6.6](https://github.com/truocphan/json-duplicate-keys/tree/2025.6.6)
435
+ - [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
436
+
437
+ #### [json-duplicate-keys v2024.12.12](https://github.com/truocphan/json-duplicate-keys/tree/2024.12.12)
438
+ - **New**: _insert_ function
439
+
400
440
  #### [json-duplicate-keys v2024.11.28](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.28)
401
441
  - **Fixed**: Add subkey name to empty dict of existing key name
402
442
 
@@ -1,8 +1,9 @@
1
+ from json_duplicate_keys import json_duplicate_keys_VERSION
1
2
  import setuptools
2
3
 
3
4
  setuptools.setup(
4
5
  name="json-duplicate-keys",
5
- version="2024.11.28",
6
+ version=json_duplicate_keys_VERSION,
6
7
  author="TP Cyber Security",
7
8
  license="MIT",
8
9
  author_email="tpcybersec2023@gmail.com",
@@ -17,5 +18,5 @@ setuptools.setup(
17
18
  "Programming Language :: Python :: Implementation :: Jython"
18
19
  ],
19
20
  keywords=["TPCyberSec", "json", "duplicate keys", "json duplicate keys", "flatten", "unflatten"],
20
- packages=["json_duplicate_keys"],
21
+ packages=setuptools.find_packages(),
21
22
  )