json-duplicate-keys 2025.8.19__tar.gz → 2025.9.9__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.
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/PKG-INFO +58 -62
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/README.md +55 -39
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys/__init__.py +8 -2
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys.egg-info/PKG-INFO +58 -62
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/pyproject.toml +3 -3
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/LICENSE +0 -0
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys.egg-info/SOURCES.txt +0 -0
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys.egg-info/dependency_links.txt +0 -0
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys.egg-info/top_level.txt +0 -0
- {json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/setup.cfg +0 -0
@@ -1,30 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2025.
|
3
|
+
Version: 2025.9.9
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
5
|
Author-email: TP Cyber Security <tpcybersec2023@gmail.com>
|
6
|
-
License: MIT
|
7
|
-
|
8
|
-
Copyright (c) 2022 TP Cyber Security
|
9
|
-
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
12
|
-
in the Software without restriction, including without limitation the rights
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
15
|
-
furnished to do so, subject to the following conditions:
|
16
|
-
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
18
|
-
copies or substantial portions of the Software.
|
19
|
-
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
-
SOFTWARE.
|
27
|
-
Project-URL: Homepage, https://github.com/tpcybersec/json-duplicate-keys
|
6
|
+
License: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/TPCyberSec/json-duplicate-keys
|
28
8
|
Keywords: TPCyberSec,json,duplicate keys,json duplicate keys,flatten,unflatten
|
29
9
|
Classifier: Programming Language :: Python :: 3
|
30
10
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
@@ -35,32 +15,34 @@ License-File: LICENSE
|
|
35
15
|
<h1>JSON Duplicate Keys - PyPI</h1>
|
36
16
|
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
37
17
|
<br><br>
|
38
|
-
<a href="https://github.com/
|
39
|
-
<a href="#"><img src="https://img.shields.io/github/downloads/
|
40
|
-
<a href="#"><img src="https://img.shields.io/github/stars/
|
41
|
-
<a href="#"><img src="https://img.shields.io/github/forks/
|
42
|
-
<a href="https://github.com/
|
43
|
-
<a href="https://github.com/
|
18
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/TPCyberSec/json-duplicate-keys" height=30></a>
|
19
|
+
<a href="#"><img src="https://img.shields.io/github/downloads/TPCyberSec/json-duplicate-keys/total" height=30></a>
|
20
|
+
<a href="#"><img src="https://img.shields.io/github/stars/TPCyberSec/json-duplicate-keys" height=30></a>
|
21
|
+
<a href="#"><img src="https://img.shields.io/github/forks/TPCyberSec/json-duplicate-keys" height=30></a>
|
22
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/TPCyberSec/json-duplicate-keys" height=30></a>
|
23
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/TPCyberSec/json-duplicate-keys" height=30></a>
|
44
24
|
<br>
|
45
25
|
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
|
46
26
|
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
47
27
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
48
28
|
</div>
|
49
29
|
|
50
|
-
|
30
|
+
---
|
31
|
+
# 🛠️ Installation
|
51
32
|
#### From PyPI:
|
52
33
|
```console
|
53
34
|
pip install json-duplicate-keys
|
54
35
|
```
|
55
36
|
#### From Source:
|
56
37
|
```console
|
57
|
-
git clone https://github.com/
|
38
|
+
git clone https://github.com/TPCyberSec/json-duplicate-keys.git --branch <Branch/Tag>
|
58
39
|
cd json-duplicate-keys
|
59
40
|
python -m build
|
60
41
|
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
61
42
|
```
|
62
43
|
|
63
|
-
|
44
|
+
---
|
45
|
+
# 📘 Basic Usage
|
64
46
|
### normalize_key(`name`, `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
65
47
|
_Normalize Key name_
|
66
48
|
- `name`: key name
|
@@ -73,8 +55,8 @@ import json_duplicate_keys as jdks
|
|
73
55
|
print(jdks.normalize_key("version{{{_2_}}}"))
|
74
56
|
# OUTPUT: version
|
75
57
|
```
|
76
|
-
---
|
77
58
|
|
59
|
+
---
|
78
60
|
### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
79
61
|
_Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
|
80
62
|
- `Jstr`: a JSON format string
|
@@ -93,8 +75,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
93
75
|
print(JDKSObject)
|
94
76
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE987940>
|
95
77
|
```
|
96
|
-
---
|
97
78
|
|
79
|
+
---
|
98
80
|
### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
99
81
|
_Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
|
100
82
|
- `Jfilepath`: The path to the file containing the JSON format string
|
@@ -115,8 +97,8 @@ JDKSObject = jdks.load(Jfilepath)
|
|
115
97
|
print(JDKSObject)
|
116
98
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE986D40>
|
117
99
|
```
|
118
|
-
---
|
119
100
|
|
101
|
+
---
|
120
102
|
### JSON_DUPLICATE_KEYS.getObject()
|
121
103
|
_Get the JSON object_
|
122
104
|
```python
|
@@ -129,8 +111,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
129
111
|
print(JDKSObject.getObject())
|
130
112
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
131
113
|
```
|
132
|
-
---
|
133
114
|
|
115
|
+
---
|
134
116
|
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
135
117
|
_Get value in the JSON object by `name`_
|
136
118
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -154,8 +136,8 @@ print(JDKSObject.get("release||$0$"))
|
|
154
136
|
print(JDKSObject.get("snapshot||author"))
|
155
137
|
# OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
|
156
138
|
```
|
157
|
-
---
|
158
139
|
|
140
|
+
---
|
159
141
|
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
160
142
|
_Set a new `name` and `value` for the JSON object_
|
161
143
|
- `name`: new key name for the JSON object. Supported flat key name format
|
@@ -200,8 +182,8 @@ JDKSObject.set("snapshot||author", "truocphan")
|
|
200
182
|
print(JDKSObject.getObject())
|
201
183
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan'}}
|
202
184
|
```
|
203
|
-
---
|
204
185
|
|
186
|
+
---
|
205
187
|
### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
206
188
|
_Insert `value` at `position` in value list of `name`_
|
207
189
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -228,9 +210,19 @@ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
|
|
228
210
|
|
229
211
|
print(JDKSObject.getObject())
|
230
212
|
# 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'}]}}
|
213
|
+
|
214
|
+
|
215
|
+
JDKSObject = jdks.loads("[]")
|
216
|
+
|
217
|
+
JDKSObject.insert(None, {"release": []})
|
218
|
+
JDKSObject.insert(None, {"author": "truocphan"}, 0)
|
219
|
+
JDKSObject.insert("$1$||release", {"version": "2025.9.9"})
|
220
|
+
|
221
|
+
print(JDKSObject.getObject())
|
222
|
+
# OUTPUT: [{'author': 'truocphan'}, {'release': [{'version': '2025.9.9'}]}]
|
231
223
|
```
|
232
|
-
---
|
233
224
|
|
225
|
+
---
|
234
226
|
### 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)
|
235
227
|
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
|
236
228
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -259,8 +251,8 @@ JDKSObject.update("snapshot||version", "latest")
|
|
259
251
|
print(JDKSObject.getObject())
|
260
252
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': ['22.3.3', 'latest'], 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': 'latest', 'release': [{'version': 'latest'}]}}
|
261
253
|
```
|
262
|
-
---
|
263
254
|
|
255
|
+
---
|
264
256
|
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
265
257
|
_Delete a key-value pair in a JSON object by key `name`_
|
266
258
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -285,8 +277,8 @@ JDKSObject.delete("snapshot")
|
|
285
277
|
print(JDKSObject.getObject())
|
286
278
|
# OUTPUT: {'author': 'truocphan', 'version{{{_2_}}}': 'latest', 'release': []}
|
287
279
|
```
|
288
|
-
---
|
289
280
|
|
281
|
+
---
|
290
282
|
### JSON_DUPLICATE_KEYS.filter_keys(`name`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
291
283
|
_Return a `JSON_DUPLICATE_KEYS` object with keys matching a pattern_
|
292
284
|
- `name`:
|
@@ -306,8 +298,8 @@ print(JDKSObject.filter_keys("version").dumps())
|
|
306
298
|
print(JDKSObject.dumps())
|
307
299
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
308
300
|
```
|
309
|
-
---
|
310
301
|
|
302
|
+
---
|
311
303
|
### JSON_DUPLICATE_KEYS.filter_values(`value`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
312
304
|
_Return a `JSON_DUPLICATE_KEYS` object with values matching a pattern_
|
313
305
|
- `value`:
|
@@ -327,8 +319,8 @@ print(JDKSObject.filter_values("latest").dumps())
|
|
327
319
|
print(JDKSObject.dumps())
|
328
320
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
329
321
|
```
|
330
|
-
---
|
331
322
|
|
323
|
+
---
|
332
324
|
### JSON_DUPLICATE_KEYS.dumps(`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)
|
333
325
|
_Serialize a JSON object to a JSON format string_
|
334
326
|
- `dupSign_start`: Start symbol for marking duplicates (default: `{{{`)
|
@@ -352,8 +344,8 @@ JDKSObject.delete("snapshot")
|
|
352
344
|
print(JDKSObject.dumps())
|
353
345
|
# OUTPUT: {"author": "truocphan", "version": "latest", "release": []}
|
354
346
|
```
|
355
|
-
---
|
356
347
|
|
348
|
+
---
|
357
349
|
### JSON_DUPLICATE_KEYS.dump(`Jfilepath`, `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)
|
358
350
|
_Serialize a JSON object to a JSON format string and write to a file_
|
359
351
|
- `Jfilepath`: the path to the file to save the JSON format string
|
@@ -382,8 +374,8 @@ JDKSObject_load = jdks.load(Jfilepath)
|
|
382
374
|
print(JDKSObject_load.getObject())
|
383
375
|
# OUTPUT: {'author': 'truocphan', 'version': 'latest', 'release': []}
|
384
376
|
```
|
385
|
-
---
|
386
377
|
|
378
|
+
---
|
387
379
|
### JSON_DUPLICATE_KEYS.flatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
388
380
|
_Flatten a JSON object to a single key-value pairs_
|
389
381
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -405,8 +397,8 @@ JDKSObject.flatten()
|
|
405
397
|
print(JDKSObject.getObject())
|
406
398
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release||$0$||version': 'latest', 'snapshot||author': 'truocphan', 'snapshot||version': '22.3.3', 'snapshot||release||$0$||version': 'latest'}
|
407
399
|
```
|
408
|
-
---
|
409
400
|
|
401
|
+
---
|
410
402
|
### JSON_DUPLICATE_KEYS.unflatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
411
403
|
_Unflatten a flattened JSON object back to a JSON object_
|
412
404
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -428,37 +420,41 @@ JDKSObject.unflatten()
|
|
428
420
|
print(JDKSObject.getObject())
|
429
421
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
430
422
|
```
|
423
|
+
|
431
424
|
---
|
425
|
+
# 📝 CHANGELOG
|
426
|
+
### [json-duplicate-keys v2025.9.9](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.9.9)
|
427
|
+
- **Fixed**: Inserting a value with an `empty` or `null` name
|
432
428
|
|
433
|
-
|
434
|
-
|
435
|
-
-
|
436
|
-
- [**Updated**] Dump Unicode characters to a file
|
429
|
+
### [json-duplicate-keys v2025.8.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.8.19)
|
430
|
+
- **Updated**: Add an exception when loading a non-existent file
|
431
|
+
- **Updated**: Dump Unicode characters to a file
|
437
432
|
|
438
|
-
|
439
|
-
-
|
440
|
-
-
|
441
|
-
-
|
433
|
+
### [json-duplicate-keys v2025.7.1](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.7.1)
|
434
|
+
- **Updated**: Fixed some issues when loading JSON strings with `skipDuplicated` option
|
435
|
+
- **Updated**: Allow loading of JSON data in byte string format
|
436
|
+
- **Updated**: Issue with getting and setting an empty list
|
442
437
|
|
443
|
-
|
444
|
-
-
|
438
|
+
### [json-duplicate-keys v2025.6.6](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.6.6)
|
439
|
+
- **Updated** Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
445
440
|
|
446
|
-
|
441
|
+
### [json-duplicate-keys v2024.12.12](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.12.12)
|
447
442
|
- **New**: _insert_ function
|
448
443
|
|
449
|
-
|
444
|
+
### [json-duplicate-keys v2024.11.28](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.28)
|
450
445
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
451
446
|
|
452
|
-
|
447
|
+
### [json-duplicate-keys v2024.11.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.19)
|
453
448
|
- **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
|
454
449
|
|
455
|
-
|
450
|
+
### [json-duplicate-keys v2024.7.17](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.7.17)
|
456
451
|
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
457
452
|
|
458
|
-
|
453
|
+
### [json-duplicate-keys v2024.4.20](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.4.20)
|
459
454
|
- **New**: _filter_values_
|
460
455
|
- **Updated**: _filter_keys_
|
461
456
|
|
462
|
-
|
457
|
+
### [json-duplicate-keys v2024.3.24](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.3.24)
|
463
458
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
459
|
+
|
464
460
|
---
|
@@ -2,32 +2,34 @@
|
|
2
2
|
<h1>JSON Duplicate Keys - PyPI</h1>
|
3
3
|
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
4
4
|
<br><br>
|
5
|
-
<a href="https://github.com/
|
6
|
-
<a href="#"><img src="https://img.shields.io/github/downloads/
|
7
|
-
<a href="#"><img src="https://img.shields.io/github/stars/
|
8
|
-
<a href="#"><img src="https://img.shields.io/github/forks/
|
9
|
-
<a href="https://github.com/
|
10
|
-
<a href="https://github.com/
|
5
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/TPCyberSec/json-duplicate-keys" height=30></a>
|
6
|
+
<a href="#"><img src="https://img.shields.io/github/downloads/TPCyberSec/json-duplicate-keys/total" height=30></a>
|
7
|
+
<a href="#"><img src="https://img.shields.io/github/stars/TPCyberSec/json-duplicate-keys" height=30></a>
|
8
|
+
<a href="#"><img src="https://img.shields.io/github/forks/TPCyberSec/json-duplicate-keys" height=30></a>
|
9
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/TPCyberSec/json-duplicate-keys" height=30></a>
|
10
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/TPCyberSec/json-duplicate-keys" height=30></a>
|
11
11
|
<br>
|
12
12
|
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
|
13
13
|
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
14
14
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
15
15
|
</div>
|
16
16
|
|
17
|
-
|
17
|
+
---
|
18
|
+
# 🛠️ Installation
|
18
19
|
#### From PyPI:
|
19
20
|
```console
|
20
21
|
pip install json-duplicate-keys
|
21
22
|
```
|
22
23
|
#### From Source:
|
23
24
|
```console
|
24
|
-
git clone https://github.com/
|
25
|
+
git clone https://github.com/TPCyberSec/json-duplicate-keys.git --branch <Branch/Tag>
|
25
26
|
cd json-duplicate-keys
|
26
27
|
python -m build
|
27
28
|
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
28
29
|
```
|
29
30
|
|
30
|
-
|
31
|
+
---
|
32
|
+
# 📘 Basic Usage
|
31
33
|
### normalize_key(`name`, `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
32
34
|
_Normalize Key name_
|
33
35
|
- `name`: key name
|
@@ -40,8 +42,8 @@ import json_duplicate_keys as jdks
|
|
40
42
|
print(jdks.normalize_key("version{{{_2_}}}"))
|
41
43
|
# OUTPUT: version
|
42
44
|
```
|
43
|
-
---
|
44
45
|
|
46
|
+
---
|
45
47
|
### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
46
48
|
_Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
|
47
49
|
- `Jstr`: a JSON format string
|
@@ -60,8 +62,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
60
62
|
print(JDKSObject)
|
61
63
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE987940>
|
62
64
|
```
|
63
|
-
---
|
64
65
|
|
66
|
+
---
|
65
67
|
### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
66
68
|
_Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
|
67
69
|
- `Jfilepath`: The path to the file containing the JSON format string
|
@@ -82,8 +84,8 @@ JDKSObject = jdks.load(Jfilepath)
|
|
82
84
|
print(JDKSObject)
|
83
85
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE986D40>
|
84
86
|
```
|
85
|
-
---
|
86
87
|
|
88
|
+
---
|
87
89
|
### JSON_DUPLICATE_KEYS.getObject()
|
88
90
|
_Get the JSON object_
|
89
91
|
```python
|
@@ -96,8 +98,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
96
98
|
print(JDKSObject.getObject())
|
97
99
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
98
100
|
```
|
99
|
-
---
|
100
101
|
|
102
|
+
---
|
101
103
|
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
102
104
|
_Get value in the JSON object by `name`_
|
103
105
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -121,8 +123,8 @@ print(JDKSObject.get("release||$0$"))
|
|
121
123
|
print(JDKSObject.get("snapshot||author"))
|
122
124
|
# OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
|
123
125
|
```
|
124
|
-
---
|
125
126
|
|
127
|
+
---
|
126
128
|
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
127
129
|
_Set a new `name` and `value` for the JSON object_
|
128
130
|
- `name`: new key name for the JSON object. Supported flat key name format
|
@@ -167,8 +169,8 @@ JDKSObject.set("snapshot||author", "truocphan")
|
|
167
169
|
print(JDKSObject.getObject())
|
168
170
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan'}}
|
169
171
|
```
|
170
|
-
---
|
171
172
|
|
173
|
+
---
|
172
174
|
### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
173
175
|
_Insert `value` at `position` in value list of `name`_
|
174
176
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -195,9 +197,19 @@ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
|
|
195
197
|
|
196
198
|
print(JDKSObject.getObject())
|
197
199
|
# 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'}]}}
|
200
|
+
|
201
|
+
|
202
|
+
JDKSObject = jdks.loads("[]")
|
203
|
+
|
204
|
+
JDKSObject.insert(None, {"release": []})
|
205
|
+
JDKSObject.insert(None, {"author": "truocphan"}, 0)
|
206
|
+
JDKSObject.insert("$1$||release", {"version": "2025.9.9"})
|
207
|
+
|
208
|
+
print(JDKSObject.getObject())
|
209
|
+
# OUTPUT: [{'author': 'truocphan'}, {'release': [{'version': '2025.9.9'}]}]
|
198
210
|
```
|
199
|
-
---
|
200
211
|
|
212
|
+
---
|
201
213
|
### 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)
|
202
214
|
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
|
203
215
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -226,8 +238,8 @@ JDKSObject.update("snapshot||version", "latest")
|
|
226
238
|
print(JDKSObject.getObject())
|
227
239
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': ['22.3.3', 'latest'], 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': 'latest', 'release': [{'version': 'latest'}]}}
|
228
240
|
```
|
229
|
-
---
|
230
241
|
|
242
|
+
---
|
231
243
|
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
232
244
|
_Delete a key-value pair in a JSON object by key `name`_
|
233
245
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -252,8 +264,8 @@ JDKSObject.delete("snapshot")
|
|
252
264
|
print(JDKSObject.getObject())
|
253
265
|
# OUTPUT: {'author': 'truocphan', 'version{{{_2_}}}': 'latest', 'release': []}
|
254
266
|
```
|
255
|
-
---
|
256
267
|
|
268
|
+
---
|
257
269
|
### JSON_DUPLICATE_KEYS.filter_keys(`name`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
258
270
|
_Return a `JSON_DUPLICATE_KEYS` object with keys matching a pattern_
|
259
271
|
- `name`:
|
@@ -273,8 +285,8 @@ print(JDKSObject.filter_keys("version").dumps())
|
|
273
285
|
print(JDKSObject.dumps())
|
274
286
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
275
287
|
```
|
276
|
-
---
|
277
288
|
|
289
|
+
---
|
278
290
|
### JSON_DUPLICATE_KEYS.filter_values(`value`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
279
291
|
_Return a `JSON_DUPLICATE_KEYS` object with values matching a pattern_
|
280
292
|
- `value`:
|
@@ -294,8 +306,8 @@ print(JDKSObject.filter_values("latest").dumps())
|
|
294
306
|
print(JDKSObject.dumps())
|
295
307
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
296
308
|
```
|
297
|
-
---
|
298
309
|
|
310
|
+
---
|
299
311
|
### JSON_DUPLICATE_KEYS.dumps(`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)
|
300
312
|
_Serialize a JSON object to a JSON format string_
|
301
313
|
- `dupSign_start`: Start symbol for marking duplicates (default: `{{{`)
|
@@ -319,8 +331,8 @@ JDKSObject.delete("snapshot")
|
|
319
331
|
print(JDKSObject.dumps())
|
320
332
|
# OUTPUT: {"author": "truocphan", "version": "latest", "release": []}
|
321
333
|
```
|
322
|
-
---
|
323
334
|
|
335
|
+
---
|
324
336
|
### JSON_DUPLICATE_KEYS.dump(`Jfilepath`, `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)
|
325
337
|
_Serialize a JSON object to a JSON format string and write to a file_
|
326
338
|
- `Jfilepath`: the path to the file to save the JSON format string
|
@@ -349,8 +361,8 @@ JDKSObject_load = jdks.load(Jfilepath)
|
|
349
361
|
print(JDKSObject_load.getObject())
|
350
362
|
# OUTPUT: {'author': 'truocphan', 'version': 'latest', 'release': []}
|
351
363
|
```
|
352
|
-
---
|
353
364
|
|
365
|
+
---
|
354
366
|
### JSON_DUPLICATE_KEYS.flatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
355
367
|
_Flatten a JSON object to a single key-value pairs_
|
356
368
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -372,8 +384,8 @@ JDKSObject.flatten()
|
|
372
384
|
print(JDKSObject.getObject())
|
373
385
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release||$0$||version': 'latest', 'snapshot||author': 'truocphan', 'snapshot||version': '22.3.3', 'snapshot||release||$0$||version': 'latest'}
|
374
386
|
```
|
375
|
-
---
|
376
387
|
|
388
|
+
---
|
377
389
|
### JSON_DUPLICATE_KEYS.unflatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
378
390
|
_Unflatten a flattened JSON object back to a JSON object_
|
379
391
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -395,37 +407,41 @@ JDKSObject.unflatten()
|
|
395
407
|
print(JDKSObject.getObject())
|
396
408
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
397
409
|
```
|
410
|
+
|
398
411
|
---
|
412
|
+
# 📝 CHANGELOG
|
413
|
+
### [json-duplicate-keys v2025.9.9](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.9.9)
|
414
|
+
- **Fixed**: Inserting a value with an `empty` or `null` name
|
399
415
|
|
400
|
-
|
401
|
-
|
402
|
-
-
|
403
|
-
- [**Updated**] Dump Unicode characters to a file
|
416
|
+
### [json-duplicate-keys v2025.8.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.8.19)
|
417
|
+
- **Updated**: Add an exception when loading a non-existent file
|
418
|
+
- **Updated**: Dump Unicode characters to a file
|
404
419
|
|
405
|
-
|
406
|
-
-
|
407
|
-
-
|
408
|
-
-
|
420
|
+
### [json-duplicate-keys v2025.7.1](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.7.1)
|
421
|
+
- **Updated**: Fixed some issues when loading JSON strings with `skipDuplicated` option
|
422
|
+
- **Updated**: Allow loading of JSON data in byte string format
|
423
|
+
- **Updated**: Issue with getting and setting an empty list
|
409
424
|
|
410
|
-
|
411
|
-
-
|
425
|
+
### [json-duplicate-keys v2025.6.6](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.6.6)
|
426
|
+
- **Updated** Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
412
427
|
|
413
|
-
|
428
|
+
### [json-duplicate-keys v2024.12.12](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.12.12)
|
414
429
|
- **New**: _insert_ function
|
415
430
|
|
416
|
-
|
431
|
+
### [json-duplicate-keys v2024.11.28](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.28)
|
417
432
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
418
433
|
|
419
|
-
|
434
|
+
### [json-duplicate-keys v2024.11.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.19)
|
420
435
|
- **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
|
421
436
|
|
422
|
-
|
437
|
+
### [json-duplicate-keys v2024.7.17](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.7.17)
|
423
438
|
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
424
439
|
|
425
|
-
|
440
|
+
### [json-duplicate-keys v2024.4.20](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.4.20)
|
426
441
|
- **New**: _filter_values_
|
427
442
|
- **Updated**: _filter_keys_
|
428
443
|
|
429
|
-
|
444
|
+
### [json-duplicate-keys v2024.3.24](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.3.24)
|
430
445
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
446
|
+
|
431
447
|
---
|
{json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys/__init__.py
RENAMED
@@ -362,8 +362,8 @@ class JSON_DUPLICATE_KEYS:
|
|
362
362
|
# User input data type validation
|
363
363
|
if type(_isDebug_) != bool: _isDebug_ = False
|
364
364
|
|
365
|
-
if type(name) not in [str, unicode]:
|
366
|
-
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or
|
365
|
+
if type(name) not in [str, unicode, type(None)]:
|
366
|
+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str, unicode or None, not {}\x1b[0m".format(type(name)))
|
367
367
|
return False
|
368
368
|
|
369
369
|
if type(position) != int: position = None
|
@@ -381,6 +381,12 @@ class JSON_DUPLICATE_KEYS:
|
|
381
381
|
if type(self.getObject()) not in [list, dict, OrderedDict]:
|
382
382
|
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
|
383
383
|
return False
|
384
|
+
|
385
|
+
if (name is None or name == "") and type(self.getObject()) == list:
|
386
|
+
if position is None: position = len(self.getObject())
|
387
|
+
|
388
|
+
self.getObject().insert(position, value)
|
389
|
+
return True
|
384
390
|
|
385
391
|
if re.search(re.escape(separator)+"$", name):
|
386
392
|
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
|
{json_duplicate_keys-2025.8.19 → json_duplicate_keys-2025.9.9}/json_duplicate_keys.egg-info/PKG-INFO
RENAMED
@@ -1,30 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2025.
|
3
|
+
Version: 2025.9.9
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
5
|
Author-email: TP Cyber Security <tpcybersec2023@gmail.com>
|
6
|
-
License: MIT
|
7
|
-
|
8
|
-
Copyright (c) 2022 TP Cyber Security
|
9
|
-
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
12
|
-
in the Software without restriction, including without limitation the rights
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
15
|
-
furnished to do so, subject to the following conditions:
|
16
|
-
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
18
|
-
copies or substantial portions of the Software.
|
19
|
-
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
-
SOFTWARE.
|
27
|
-
Project-URL: Homepage, https://github.com/tpcybersec/json-duplicate-keys
|
6
|
+
License: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/TPCyberSec/json-duplicate-keys
|
28
8
|
Keywords: TPCyberSec,json,duplicate keys,json duplicate keys,flatten,unflatten
|
29
9
|
Classifier: Programming Language :: Python :: 3
|
30
10
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
@@ -35,32 +15,34 @@ License-File: LICENSE
|
|
35
15
|
<h1>JSON Duplicate Keys - PyPI</h1>
|
36
16
|
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
37
17
|
<br><br>
|
38
|
-
<a href="https://github.com/
|
39
|
-
<a href="#"><img src="https://img.shields.io/github/downloads/
|
40
|
-
<a href="#"><img src="https://img.shields.io/github/stars/
|
41
|
-
<a href="#"><img src="https://img.shields.io/github/forks/
|
42
|
-
<a href="https://github.com/
|
43
|
-
<a href="https://github.com/
|
18
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/TPCyberSec/json-duplicate-keys" height=30></a>
|
19
|
+
<a href="#"><img src="https://img.shields.io/github/downloads/TPCyberSec/json-duplicate-keys/total" height=30></a>
|
20
|
+
<a href="#"><img src="https://img.shields.io/github/stars/TPCyberSec/json-duplicate-keys" height=30></a>
|
21
|
+
<a href="#"><img src="https://img.shields.io/github/forks/TPCyberSec/json-duplicate-keys" height=30></a>
|
22
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/TPCyberSec/json-duplicate-keys" height=30></a>
|
23
|
+
<a href="https://github.com/TPCyberSec/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/TPCyberSec/json-duplicate-keys" height=30></a>
|
44
24
|
<br>
|
45
25
|
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
|
46
26
|
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
47
27
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
48
28
|
</div>
|
49
29
|
|
50
|
-
|
30
|
+
---
|
31
|
+
# 🛠️ Installation
|
51
32
|
#### From PyPI:
|
52
33
|
```console
|
53
34
|
pip install json-duplicate-keys
|
54
35
|
```
|
55
36
|
#### From Source:
|
56
37
|
```console
|
57
|
-
git clone https://github.com/
|
38
|
+
git clone https://github.com/TPCyberSec/json-duplicate-keys.git --branch <Branch/Tag>
|
58
39
|
cd json-duplicate-keys
|
59
40
|
python -m build
|
60
41
|
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
61
42
|
```
|
62
43
|
|
63
|
-
|
44
|
+
---
|
45
|
+
# 📘 Basic Usage
|
64
46
|
### normalize_key(`name`, `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
65
47
|
_Normalize Key name_
|
66
48
|
- `name`: key name
|
@@ -73,8 +55,8 @@ import json_duplicate_keys as jdks
|
|
73
55
|
print(jdks.normalize_key("version{{{_2_}}}"))
|
74
56
|
# OUTPUT: version
|
75
57
|
```
|
76
|
-
---
|
77
58
|
|
59
|
+
---
|
78
60
|
### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
79
61
|
_Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
|
80
62
|
- `Jstr`: a JSON format string
|
@@ -93,8 +75,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
93
75
|
print(JDKSObject)
|
94
76
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE987940>
|
95
77
|
```
|
96
|
-
---
|
97
78
|
|
79
|
+
---
|
98
80
|
### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
|
99
81
|
_Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
|
100
82
|
- `Jfilepath`: The path to the file containing the JSON format string
|
@@ -115,8 +97,8 @@ JDKSObject = jdks.load(Jfilepath)
|
|
115
97
|
print(JDKSObject)
|
116
98
|
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE986D40>
|
117
99
|
```
|
118
|
-
---
|
119
100
|
|
101
|
+
---
|
120
102
|
### JSON_DUPLICATE_KEYS.getObject()
|
121
103
|
_Get the JSON object_
|
122
104
|
```python
|
@@ -129,8 +111,8 @@ JDKSObject = jdks.loads(Jstr)
|
|
129
111
|
print(JDKSObject.getObject())
|
130
112
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
131
113
|
```
|
132
|
-
---
|
133
114
|
|
115
|
+
---
|
134
116
|
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
135
117
|
_Get value in the JSON object by `name`_
|
136
118
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -154,8 +136,8 @@ print(JDKSObject.get("release||$0$"))
|
|
154
136
|
print(JDKSObject.get("snapshot||author"))
|
155
137
|
# OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
|
156
138
|
```
|
157
|
-
---
|
158
139
|
|
140
|
+
---
|
159
141
|
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
|
160
142
|
_Set a new `name` and `value` for the JSON object_
|
161
143
|
- `name`: new key name for the JSON object. Supported flat key name format
|
@@ -200,8 +182,8 @@ JDKSObject.set("snapshot||author", "truocphan")
|
|
200
182
|
print(JDKSObject.getObject())
|
201
183
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan'}}
|
202
184
|
```
|
203
|
-
---
|
204
185
|
|
186
|
+
---
|
205
187
|
### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
|
206
188
|
_Insert `value` at `position` in value list of `name`_
|
207
189
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -228,9 +210,19 @@ JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
|
|
228
210
|
|
229
211
|
print(JDKSObject.getObject())
|
230
212
|
# 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'}]}}
|
213
|
+
|
214
|
+
|
215
|
+
JDKSObject = jdks.loads("[]")
|
216
|
+
|
217
|
+
JDKSObject.insert(None, {"release": []})
|
218
|
+
JDKSObject.insert(None, {"author": "truocphan"}, 0)
|
219
|
+
JDKSObject.insert("$1$||release", {"version": "2025.9.9"})
|
220
|
+
|
221
|
+
print(JDKSObject.getObject())
|
222
|
+
# OUTPUT: [{'author': 'truocphan'}, {'release': [{'version': '2025.9.9'}]}]
|
231
223
|
```
|
232
|
-
---
|
233
224
|
|
225
|
+
---
|
234
226
|
### 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)
|
235
227
|
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
|
236
228
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -259,8 +251,8 @@ JDKSObject.update("snapshot||version", "latest")
|
|
259
251
|
print(JDKSObject.getObject())
|
260
252
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': ['22.3.3', 'latest'], 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': 'latest', 'release': [{'version': 'latest'}]}}
|
261
253
|
```
|
262
|
-
---
|
263
254
|
|
255
|
+
---
|
264
256
|
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
|
265
257
|
_Delete a key-value pair in a JSON object by key `name`_
|
266
258
|
- `name`: the key name of the JSON object. Supported flatten key name format
|
@@ -285,8 +277,8 @@ JDKSObject.delete("snapshot")
|
|
285
277
|
print(JDKSObject.getObject())
|
286
278
|
# OUTPUT: {'author': 'truocphan', 'version{{{_2_}}}': 'latest', 'release': []}
|
287
279
|
```
|
288
|
-
---
|
289
280
|
|
281
|
+
---
|
290
282
|
### JSON_DUPLICATE_KEYS.filter_keys(`name`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
291
283
|
_Return a `JSON_DUPLICATE_KEYS` object with keys matching a pattern_
|
292
284
|
- `name`:
|
@@ -306,8 +298,8 @@ print(JDKSObject.filter_keys("version").dumps())
|
|
306
298
|
print(JDKSObject.dumps())
|
307
299
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
308
300
|
```
|
309
|
-
---
|
310
301
|
|
302
|
+
---
|
311
303
|
### JSON_DUPLICATE_KEYS.filter_values(`value`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
|
312
304
|
_Return a `JSON_DUPLICATE_KEYS` object with values matching a pattern_
|
313
305
|
- `value`:
|
@@ -327,8 +319,8 @@ print(JDKSObject.filter_values("latest").dumps())
|
|
327
319
|
print(JDKSObject.dumps())
|
328
320
|
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
|
329
321
|
```
|
330
|
-
---
|
331
322
|
|
323
|
+
---
|
332
324
|
### JSON_DUPLICATE_KEYS.dumps(`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)
|
333
325
|
_Serialize a JSON object to a JSON format string_
|
334
326
|
- `dupSign_start`: Start symbol for marking duplicates (default: `{{{`)
|
@@ -352,8 +344,8 @@ JDKSObject.delete("snapshot")
|
|
352
344
|
print(JDKSObject.dumps())
|
353
345
|
# OUTPUT: {"author": "truocphan", "version": "latest", "release": []}
|
354
346
|
```
|
355
|
-
---
|
356
347
|
|
348
|
+
---
|
357
349
|
### JSON_DUPLICATE_KEYS.dump(`Jfilepath`, `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)
|
358
350
|
_Serialize a JSON object to a JSON format string and write to a file_
|
359
351
|
- `Jfilepath`: the path to the file to save the JSON format string
|
@@ -382,8 +374,8 @@ JDKSObject_load = jdks.load(Jfilepath)
|
|
382
374
|
print(JDKSObject_load.getObject())
|
383
375
|
# OUTPUT: {'author': 'truocphan', 'version': 'latest', 'release': []}
|
384
376
|
```
|
385
|
-
---
|
386
377
|
|
378
|
+
---
|
387
379
|
### JSON_DUPLICATE_KEYS.flatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
388
380
|
_Flatten a JSON object to a single key-value pairs_
|
389
381
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -405,8 +397,8 @@ JDKSObject.flatten()
|
|
405
397
|
print(JDKSObject.getObject())
|
406
398
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release||$0$||version': 'latest', 'snapshot||author': 'truocphan', 'snapshot||version': '22.3.3', 'snapshot||release||$0$||version': 'latest'}
|
407
399
|
```
|
408
|
-
---
|
409
400
|
|
401
|
+
---
|
410
402
|
### JSON_DUPLICATE_KEYS.unflatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
|
411
403
|
_Unflatten a flattened JSON object back to a JSON object_
|
412
404
|
- `separator`: Separator for flatten keys (default: `||`)
|
@@ -428,37 +420,41 @@ JDKSObject.unflatten()
|
|
428
420
|
print(JDKSObject.getObject())
|
429
421
|
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
|
430
422
|
```
|
423
|
+
|
431
424
|
---
|
425
|
+
# 📝 CHANGELOG
|
426
|
+
### [json-duplicate-keys v2025.9.9](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.9.9)
|
427
|
+
- **Fixed**: Inserting a value with an `empty` or `null` name
|
432
428
|
|
433
|
-
|
434
|
-
|
435
|
-
-
|
436
|
-
- [**Updated**] Dump Unicode characters to a file
|
429
|
+
### [json-duplicate-keys v2025.8.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.8.19)
|
430
|
+
- **Updated**: Add an exception when loading a non-existent file
|
431
|
+
- **Updated**: Dump Unicode characters to a file
|
437
432
|
|
438
|
-
|
439
|
-
-
|
440
|
-
-
|
441
|
-
-
|
433
|
+
### [json-duplicate-keys v2025.7.1](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.7.1)
|
434
|
+
- **Updated**: Fixed some issues when loading JSON strings with `skipDuplicated` option
|
435
|
+
- **Updated**: Allow loading of JSON data in byte string format
|
436
|
+
- **Updated**: Issue with getting and setting an empty list
|
442
437
|
|
443
|
-
|
444
|
-
-
|
438
|
+
### [json-duplicate-keys v2025.6.6](https://github.com/TPCyberSec/json-duplicate-keys/tree/2025.6.6)
|
439
|
+
- **Updated** Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
445
440
|
|
446
|
-
|
441
|
+
### [json-duplicate-keys v2024.12.12](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.12.12)
|
447
442
|
- **New**: _insert_ function
|
448
443
|
|
449
|
-
|
444
|
+
### [json-duplicate-keys v2024.11.28](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.28)
|
450
445
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
451
446
|
|
452
|
-
|
447
|
+
### [json-duplicate-keys v2024.11.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.19)
|
453
448
|
- **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
|
454
449
|
|
455
|
-
|
450
|
+
### [json-duplicate-keys v2024.7.17](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.7.17)
|
456
451
|
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
457
452
|
|
458
|
-
|
453
|
+
### [json-duplicate-keys v2024.4.20](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.4.20)
|
459
454
|
- **New**: _filter_values_
|
460
455
|
- **Updated**: _filter_keys_
|
461
456
|
|
462
|
-
|
457
|
+
### [json-duplicate-keys v2024.3.24](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.3.24)
|
463
458
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
459
|
+
|
464
460
|
---
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "json-duplicate-keys"
|
7
|
-
version = "2025.
|
7
|
+
version = "2025.9.9"
|
8
8
|
description = "Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys"
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
10
|
-
license = {
|
10
|
+
license = { text = "MIT" }
|
11
11
|
keywords = ["TPCyberSec", "json", "duplicate keys", "json duplicate keys", "flatten", "unflatten"]
|
12
12
|
classifiers = [
|
13
13
|
"Programming Language :: Python :: 3",
|
@@ -19,7 +19,7 @@ authors = [
|
|
19
19
|
]
|
20
20
|
|
21
21
|
[project.urls]
|
22
|
-
Homepage = "https://github.com/
|
22
|
+
Homepage = "https://github.com/TPCyberSec/json-duplicate-keys"
|
23
23
|
|
24
24
|
[tool.setuptools]
|
25
25
|
packages = ["json_duplicate_keys"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|