json-duplicate-keys 2025.7.1__tar.gz → 2025.8.19__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.7.1/json_duplicate_keys.egg-info → json_duplicate_keys-2025.8.19}/PKG-INFO +52 -29
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/README.md +28 -23
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/json_duplicate_keys/__init__.py +28 -26
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19/json_duplicate_keys.egg-info}/PKG-INFO +52 -29
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/json_duplicate_keys.egg-info/SOURCES.txt +1 -3
- json_duplicate_keys-2025.8.19/pyproject.toml +25 -0
- json_duplicate_keys-2025.7.1/MANIFEST.in +0 -1
- json_duplicate_keys-2025.7.1/requirements.txt +0 -0
- json_duplicate_keys-2025.7.1/setup.py +0 -22
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/LICENSE +0 -0
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/json_duplicate_keys.egg-info/dependency_links.txt +0 -0
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/json_duplicate_keys.egg-info/top_level.txt +0 -0
- {json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/setup.cfg +0 -0
{json_duplicate_keys-2025.7.1/json_duplicate_keys.egg-info → json_duplicate_keys-2025.8.19}/PKG-INFO
RENAMED
@@ -1,32 +1,51 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2025.
|
3
|
+
Version: 2025.8.19
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Author-email: TP Cyber Security <tpcybersec2023@gmail.com>
|
6
|
+
License: MIT License
|
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
|
9
28
|
Keywords: TPCyberSec,json,duplicate keys,json duplicate keys,flatten,unflatten
|
10
29
|
Classifier: Programming Language :: Python :: 3
|
11
|
-
Classifier: Programming Language :: Python :: 2
|
12
30
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
13
31
|
Description-Content-Type: text/markdown
|
14
32
|
License-File: LICENSE
|
15
33
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<
|
20
|
-
<a href="https://github.com/
|
21
|
-
<a href="#"><img src="https://img.shields.io/github/downloads/
|
22
|
-
<a href="#"><img src="https://img.shields.io/github/stars/
|
23
|
-
<a href="#"><img src="https://img.shields.io/github/forks/
|
24
|
-
<a href="https://github.com/
|
25
|
-
<a href="https://github.com/
|
34
|
+
<div align="center">
|
35
|
+
<h1>JSON Duplicate Keys - PyPI</h1>
|
36
|
+
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
37
|
+
<br><br>
|
38
|
+
<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>
|
39
|
+
<a href="#"><img src="https://img.shields.io/github/downloads/tpcybersec/json-duplicate-keys/total" height=30></a>
|
40
|
+
<a href="#"><img src="https://img.shields.io/github/stars/tpcybersec/json-duplicate-keys" height=30></a>
|
41
|
+
<a href="#"><img src="https://img.shields.io/github/forks/tpcybersec/json-duplicate-keys" height=30></a>
|
42
|
+
<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>
|
43
|
+
<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>
|
26
44
|
<br>
|
27
45
|
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
|
46
|
+
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
28
47
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
29
|
-
</
|
48
|
+
</div>
|
30
49
|
|
31
50
|
## Installation
|
32
51
|
#### From PyPI:
|
@@ -35,10 +54,10 @@ pip install json-duplicate-keys
|
|
35
54
|
```
|
36
55
|
#### From Source:
|
37
56
|
```console
|
38
|
-
git clone https://github.com/
|
57
|
+
git clone https://github.com/tpcybersec/json-duplicate-keys.git --branch <Branch/Tag>
|
39
58
|
cd json-duplicate-keys
|
40
|
-
python
|
41
|
-
python
|
59
|
+
python -m build
|
60
|
+
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
42
61
|
```
|
43
62
|
|
44
63
|
## Basic Usage
|
@@ -412,30 +431,34 @@ print(JDKSObject.getObject())
|
|
412
431
|
---
|
413
432
|
|
414
433
|
## CHANGELOG
|
415
|
-
#### [json-duplicate-keys v2025.
|
434
|
+
#### [json-duplicate-keys v2025.8.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.8.19)
|
435
|
+
- [**Updated**] Add an exception when loading a non-existent file
|
436
|
+
- [**Updated**] Dump Unicode characters to a file
|
437
|
+
|
438
|
+
#### [json-duplicate-keys v2025.7.1](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.7.1)
|
416
439
|
- [**Updated**] Fixed some issues when loading JSON strings with `skipDuplicated` option
|
417
440
|
- [**Updated**] Allow loading of JSON data in byte string format
|
418
441
|
- [**Updated**] Issue with getting and setting an empty list
|
419
442
|
|
420
|
-
#### [json-duplicate-keys v2025.6.6](https://github.com/
|
443
|
+
#### [json-duplicate-keys v2025.6.6](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.6.6)
|
421
444
|
- [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
422
445
|
|
423
|
-
#### [json-duplicate-keys v2024.12.12](https://github.com/
|
446
|
+
#### [json-duplicate-keys v2024.12.12](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.12.12)
|
424
447
|
- **New**: _insert_ function
|
425
448
|
|
426
|
-
#### [json-duplicate-keys v2024.11.28](https://github.com/
|
449
|
+
#### [json-duplicate-keys v2024.11.28](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.28)
|
427
450
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
428
451
|
|
429
|
-
#### [json-duplicate-keys v2024.11.19](https://github.com/
|
452
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.19)
|
430
453
|
- **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
|
431
454
|
|
432
|
-
#### [json-duplicate-keys v2024.7.17](https://github.com/
|
433
|
-
- **Fixed**: issue
|
455
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.7.17)
|
456
|
+
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
434
457
|
|
435
|
-
#### [json-duplicate-keys v2024.4.20](https://github.com/
|
458
|
+
#### [json-duplicate-keys v2024.4.20](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.4.20)
|
436
459
|
- **New**: _filter_values_
|
437
460
|
- **Updated**: _filter_keys_
|
438
461
|
|
439
|
-
#### [json-duplicate-keys v2024.3.24](https://github.com/
|
462
|
+
#### [json-duplicate-keys v2024.3.24](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.3.24)
|
440
463
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
441
464
|
---
|
@@ -1,17 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<
|
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/
|
1
|
+
<div align="center">
|
2
|
+
<h1>JSON Duplicate Keys - PyPI</h1>
|
3
|
+
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
4
|
+
<br><br>
|
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
|
+
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
13
14
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
14
|
-
</
|
15
|
+
</div>
|
15
16
|
|
16
17
|
## Installation
|
17
18
|
#### From PyPI:
|
@@ -20,10 +21,10 @@ pip install json-duplicate-keys
|
|
20
21
|
```
|
21
22
|
#### From Source:
|
22
23
|
```console
|
23
|
-
git clone https://github.com/
|
24
|
+
git clone https://github.com/tpcybersec/json-duplicate-keys.git --branch <Branch/Tag>
|
24
25
|
cd json-duplicate-keys
|
25
|
-
python
|
26
|
-
python
|
26
|
+
python -m build
|
27
|
+
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
27
28
|
```
|
28
29
|
|
29
30
|
## Basic Usage
|
@@ -397,30 +398,34 @@ print(JDKSObject.getObject())
|
|
397
398
|
---
|
398
399
|
|
399
400
|
## CHANGELOG
|
400
|
-
#### [json-duplicate-keys v2025.
|
401
|
+
#### [json-duplicate-keys v2025.8.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.8.19)
|
402
|
+
- [**Updated**] Add an exception when loading a non-existent file
|
403
|
+
- [**Updated**] Dump Unicode characters to a file
|
404
|
+
|
405
|
+
#### [json-duplicate-keys v2025.7.1](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.7.1)
|
401
406
|
- [**Updated**] Fixed some issues when loading JSON strings with `skipDuplicated` option
|
402
407
|
- [**Updated**] Allow loading of JSON data in byte string format
|
403
408
|
- [**Updated**] Issue with getting and setting an empty list
|
404
409
|
|
405
|
-
#### [json-duplicate-keys v2025.6.6](https://github.com/
|
410
|
+
#### [json-duplicate-keys v2025.6.6](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.6.6)
|
406
411
|
- [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
407
412
|
|
408
|
-
#### [json-duplicate-keys v2024.12.12](https://github.com/
|
413
|
+
#### [json-duplicate-keys v2024.12.12](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.12.12)
|
409
414
|
- **New**: _insert_ function
|
410
415
|
|
411
|
-
#### [json-duplicate-keys v2024.11.28](https://github.com/
|
416
|
+
#### [json-duplicate-keys v2024.11.28](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.28)
|
412
417
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
413
418
|
|
414
|
-
#### [json-duplicate-keys v2024.11.19](https://github.com/
|
419
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.19)
|
415
420
|
- **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
|
416
421
|
|
417
|
-
#### [json-duplicate-keys v2024.7.17](https://github.com/
|
418
|
-
- **Fixed**: issue
|
422
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.7.17)
|
423
|
+
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
419
424
|
|
420
|
-
#### [json-duplicate-keys v2024.4.20](https://github.com/
|
425
|
+
#### [json-duplicate-keys v2024.4.20](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.4.20)
|
421
426
|
- **New**: _filter_values_
|
422
427
|
- **Updated**: _filter_keys_
|
423
428
|
|
424
|
-
#### [json-duplicate-keys v2024.3.24](https://github.com/
|
429
|
+
#### [json-duplicate-keys v2024.3.24](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.3.24)
|
425
430
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
426
431
|
---
|
{json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19}/json_duplicate_keys/__init__.py
RENAMED
@@ -1,10 +1,8 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
json_duplicate_keys_VERSION = "2025.7.1"
|
3
|
-
|
4
2
|
try:
|
5
|
-
unicode
|
3
|
+
unicode
|
6
4
|
except NameError:
|
7
|
-
unicode = str
|
5
|
+
unicode = str
|
8
6
|
|
9
7
|
from collections import OrderedDict
|
10
8
|
import json, re, copy
|
@@ -24,7 +22,7 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
|
|
24
22
|
|
25
23
|
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
|
26
24
|
|
27
|
-
return re.sub('
|
25
|
+
return re.sub(re.escape(dupSign_start)+'_\\d+_'+re.escape(dupSign_end)+'$', "", name)
|
28
26
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
29
27
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
30
28
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -118,13 +116,13 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skip
|
|
118
116
|
Jstr = re.sub(r'"([^"]*)"[\s\t\r\n]*([,\]}])'.encode(), '\x04\x05\\1\x04\x05\\2'.encode(), Jstr)
|
119
117
|
|
120
118
|
|
121
|
-
Jstr = re.sub(r'"([^"]+)"[\s\t\r\n]*:'.encode(), r'"\1
|
119
|
+
Jstr = re.sub(r'"([^"]+)"[\s\t\r\n]*:'.encode(), (r'"\1'+dupSign_start_escape+'_dupSign_'+dupSign_end_escape+'":').encode(), Jstr)
|
122
120
|
|
123
|
-
Jstr = re.sub(r'""[\s\t\r\n]*:'.encode(), '"
|
121
|
+
Jstr = re.sub(r'""[\s\t\r\n]*:'.encode(), ('"'+dupSign_start_escape+'_dupSign_'+dupSign_end_escape+'":').encode(), Jstr)
|
124
122
|
|
125
123
|
i = 0
|
126
|
-
while re.search(r'
|
127
|
-
Jstr = re.sub(r'
|
124
|
+
while re.search((dupSign_start_escape+'_dupSign_'+dupSign_end_escape+r'"[\s\t\r\n]*:').encode(), Jstr):
|
125
|
+
Jstr = re.sub((dupSign_start_escape+'_dupSign_'+dupSign_end_escape+r'"[\s\t\r\n]*:').encode(), (dupSign_start_escape+"_"+str(i)+"_"+dupSign_end_escape+'":').encode(), Jstr, 1)
|
128
126
|
i += 1
|
129
127
|
|
130
128
|
Jstr = re.sub('\x00\x01'.encode(), r'\\\\'.encode(), Jstr)
|
@@ -135,13 +133,13 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skip
|
|
135
133
|
Jstr = re.sub(r'\\"', '\x02\x03', Jstr)
|
136
134
|
Jstr = re.sub(r'"([^"]*)"[\s\t\r\n]*([,\]}])', '\x04\x05\\1\x04\x05\\2', Jstr)
|
137
135
|
|
138
|
-
Jstr = re.sub(r'"([^"]+)"[\s\t\r\n]*:', r'"\1
|
136
|
+
Jstr = re.sub(r'"([^"]+)"[\s\t\r\n]*:', r'"\1'+dupSign_start_escape+'_dupSign_'+dupSign_end_escape+'":', Jstr)
|
139
137
|
|
140
|
-
Jstr = re.sub(r'""[\s\t\r\n]*:', '"
|
138
|
+
Jstr = re.sub(r'""[\s\t\r\n]*:', '"'+dupSign_start_escape+'_dupSign_'+dupSign_end_escape+'":', Jstr)
|
141
139
|
|
142
140
|
i = 0
|
143
|
-
while re.search(r'
|
144
|
-
Jstr = re.sub(r'
|
141
|
+
while re.search(dupSign_start_escape+'_dupSign_'+dupSign_end_escape+r'"[\s\t\r\n]*:', Jstr):
|
142
|
+
Jstr = re.sub(dupSign_start_escape+'_dupSign_'+dupSign_end_escape+r'"[\s\t\r\n]*:', dupSign_start_escape+"_"+str(i)+"_"+dupSign_end_escape+'":', Jstr, 1)
|
145
143
|
i += 1
|
146
144
|
|
147
145
|
Jstr = re.sub('\x00\x01', r'\\\\', Jstr)
|
@@ -178,11 +176,15 @@ def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skip
|
|
178
176
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
179
177
|
def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, skipDuplicated=False, _isDebug_=False):
|
180
178
|
try:
|
181
|
-
|
182
|
-
|
183
|
-
|
179
|
+
try:
|
180
|
+
with open(Jfilepath) as Jfile: Jstr = Jfile.read()
|
181
|
+
except Exception as e:
|
182
|
+
with open(Jfilepath, "rb") as Jfile: Jstr = Jfile.read()
|
184
183
|
|
185
|
-
|
184
|
+
return loads(Jstr, dupSign_start=dupSign_start, dupSign_end=dupSign_end, ordered_dict=ordered_dict, skipDuplicated=skipDuplicated, _isDebug_=_isDebug_)
|
185
|
+
except Exception as e:
|
186
|
+
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
187
|
+
return False
|
186
188
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
187
189
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
188
190
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -492,10 +494,10 @@ class JSON_DUPLICATE_KEYS:
|
|
492
494
|
for k, v in JDKSObject.getObject().items():
|
493
495
|
if type(k) == str and type(name) == str:
|
494
496
|
if re.search(name, k):
|
495
|
-
newJDKSObject.set(k, v, separator="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
|
497
|
+
newJDKSObject.set(k, v, separator=u"§§"+separator+u"§§", parse_index=u"§§"+parse_index+u"§§", ordered_dict=ordered_dict)
|
496
498
|
else:
|
497
499
|
if name == k:
|
498
|
-
newJDKSObject.set(k, v, separator="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
|
500
|
+
newJDKSObject.set(k, v, separator=u"§§"+separator+u"§§", parse_index=u"§§"+parse_index+u"§§", ordered_dict=ordered_dict)
|
499
501
|
|
500
502
|
return newJDKSObject
|
501
503
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -514,10 +516,10 @@ class JSON_DUPLICATE_KEYS:
|
|
514
516
|
for k, v in JDKSObject.getObject().items():
|
515
517
|
if type(v) == str and type(value) == str:
|
516
518
|
if re.search(value, v):
|
517
|
-
newJDKSObject.set(k, v, separator="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
|
519
|
+
newJDKSObject.set(k, v, separator=u"§§"+separator+u"§§", parse_index=u"§§"+parse_index+u"§§", ordered_dict=ordered_dict)
|
518
520
|
else:
|
519
521
|
if value == v:
|
520
|
-
newJDKSObject.set(k, v, separator="§§"+separator+"§§", parse_index="§§"+parse_index+"§§", ordered_dict=ordered_dict)
|
522
|
+
newJDKSObject.set(k, v, separator=u"§§"+separator+u"§§", parse_index=u"§§"+parse_index+u"§§", ordered_dict=ordered_dict)
|
521
523
|
|
522
524
|
return newJDKSObject
|
523
525
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -544,7 +546,7 @@ class JSON_DUPLICATE_KEYS:
|
|
544
546
|
|
545
547
|
dupSign_end_escape_regex = re.escape(json.dumps({dupSign_end:""})[2:-6])
|
546
548
|
|
547
|
-
return re.sub('
|
549
|
+
return re.sub(dupSign_start_escape_regex+'_\\d+_'+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))
|
548
550
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
549
551
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
550
552
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
@@ -557,8 +559,8 @@ class JSON_DUPLICATE_KEYS:
|
|
557
559
|
Jstr = self.dumps(dupSign_start=dupSign_start, dupSign_end=dupSign_end, _isDebug_=_isDebug_, 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)
|
558
560
|
|
559
561
|
try:
|
560
|
-
Jfile = open(Jfilepath, "
|
561
|
-
Jfile.write(Jstr)
|
562
|
+
Jfile = open(Jfilepath, "wb")
|
563
|
+
Jfile.write(Jstr.encode("utf-8"))
|
562
564
|
Jfile.close()
|
563
565
|
except Exception as e:
|
564
566
|
if _isDebug_: print("\x1b[31m[-] ExceptionError: {}\x1b[0m".format(e))
|
@@ -600,7 +602,7 @@ class JSON_DUPLICATE_KEYS:
|
|
600
602
|
else:
|
601
603
|
for k,v in Jobj.items():
|
602
604
|
_Jobj = v
|
603
|
-
_key =
|
605
|
+
_key = key+separator+k if key != None else k
|
604
606
|
|
605
607
|
__convert_Jobj_to_Jflat(_Jobj, _key)
|
606
608
|
elif type(Jobj) == list:
|
@@ -609,7 +611,7 @@ class JSON_DUPLICATE_KEYS:
|
|
609
611
|
else:
|
610
612
|
for i,v in enumerate(Jobj):
|
611
613
|
_Jobj = v
|
612
|
-
_key =
|
614
|
+
_key = key+separator+parse_index+str(i)+parse_index if key != None else parse_index+str(i)+parse_index
|
613
615
|
|
614
616
|
__convert_Jobj_to_Jflat(_Jobj, _key)
|
615
617
|
else:
|
{json_duplicate_keys-2025.7.1 → json_duplicate_keys-2025.8.19/json_duplicate_keys.egg-info}/PKG-INFO
RENAMED
@@ -1,32 +1,51 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: json-duplicate-keys
|
3
|
-
Version: 2025.
|
3
|
+
Version: 2025.8.19
|
4
4
|
Summary: Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Author-email: TP Cyber Security <tpcybersec2023@gmail.com>
|
6
|
+
License: MIT License
|
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
|
9
28
|
Keywords: TPCyberSec,json,duplicate keys,json duplicate keys,flatten,unflatten
|
10
29
|
Classifier: Programming Language :: Python :: 3
|
11
|
-
Classifier: Programming Language :: Python :: 2
|
12
30
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
13
31
|
Description-Content-Type: text/markdown
|
14
32
|
License-File: LICENSE
|
15
33
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<
|
20
|
-
<a href="https://github.com/
|
21
|
-
<a href="#"><img src="https://img.shields.io/github/downloads/
|
22
|
-
<a href="#"><img src="https://img.shields.io/github/stars/
|
23
|
-
<a href="#"><img src="https://img.shields.io/github/forks/
|
24
|
-
<a href="https://github.com/
|
25
|
-
<a href="https://github.com/
|
34
|
+
<div align="center">
|
35
|
+
<h1>JSON Duplicate Keys - PyPI</h1>
|
36
|
+
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
|
37
|
+
<br><br>
|
38
|
+
<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>
|
39
|
+
<a href="#"><img src="https://img.shields.io/github/downloads/tpcybersec/json-duplicate-keys/total" height=30></a>
|
40
|
+
<a href="#"><img src="https://img.shields.io/github/stars/tpcybersec/json-duplicate-keys" height=30></a>
|
41
|
+
<a href="#"><img src="https://img.shields.io/github/forks/tpcybersec/json-duplicate-keys" height=30></a>
|
42
|
+
<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>
|
43
|
+
<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>
|
26
44
|
<br>
|
27
45
|
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
|
46
|
+
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
|
28
47
|
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
|
29
|
-
</
|
48
|
+
</div>
|
30
49
|
|
31
50
|
## Installation
|
32
51
|
#### From PyPI:
|
@@ -35,10 +54,10 @@ pip install json-duplicate-keys
|
|
35
54
|
```
|
36
55
|
#### From Source:
|
37
56
|
```console
|
38
|
-
git clone https://github.com/
|
57
|
+
git clone https://github.com/tpcybersec/json-duplicate-keys.git --branch <Branch/Tag>
|
39
58
|
cd json-duplicate-keys
|
40
|
-
python
|
41
|
-
python
|
59
|
+
python -m build
|
60
|
+
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
|
42
61
|
```
|
43
62
|
|
44
63
|
## Basic Usage
|
@@ -412,30 +431,34 @@ print(JDKSObject.getObject())
|
|
412
431
|
---
|
413
432
|
|
414
433
|
## CHANGELOG
|
415
|
-
#### [json-duplicate-keys v2025.
|
434
|
+
#### [json-duplicate-keys v2025.8.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.8.19)
|
435
|
+
- [**Updated**] Add an exception when loading a non-existent file
|
436
|
+
- [**Updated**] Dump Unicode characters to a file
|
437
|
+
|
438
|
+
#### [json-duplicate-keys v2025.7.1](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.7.1)
|
416
439
|
- [**Updated**] Fixed some issues when loading JSON strings with `skipDuplicated` option
|
417
440
|
- [**Updated**] Allow loading of JSON data in byte string format
|
418
441
|
- [**Updated**] Issue with getting and setting an empty list
|
419
442
|
|
420
|
-
#### [json-duplicate-keys v2025.6.6](https://github.com/
|
443
|
+
#### [json-duplicate-keys v2025.6.6](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.6.6)
|
421
444
|
- [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
|
422
445
|
|
423
|
-
#### [json-duplicate-keys v2024.12.12](https://github.com/
|
446
|
+
#### [json-duplicate-keys v2024.12.12](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.12.12)
|
424
447
|
- **New**: _insert_ function
|
425
448
|
|
426
|
-
#### [json-duplicate-keys v2024.11.28](https://github.com/
|
449
|
+
#### [json-duplicate-keys v2024.11.28](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.28)
|
427
450
|
- **Fixed**: Add subkey name to empty dict of existing key name
|
428
451
|
|
429
|
-
#### [json-duplicate-keys v2024.11.19](https://github.com/
|
452
|
+
#### [json-duplicate-keys v2024.11.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.19)
|
430
453
|
- **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
|
431
454
|
|
432
|
-
#### [json-duplicate-keys v2024.7.17](https://github.com/
|
433
|
-
- **Fixed**: issue
|
455
|
+
#### [json-duplicate-keys v2024.7.17](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.7.17)
|
456
|
+
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
|
434
457
|
|
435
|
-
#### [json-duplicate-keys v2024.4.20](https://github.com/
|
458
|
+
#### [json-duplicate-keys v2024.4.20](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.4.20)
|
436
459
|
- **New**: _filter_values_
|
437
460
|
- **Updated**: _filter_keys_
|
438
461
|
|
439
|
-
#### [json-duplicate-keys v2024.3.24](https://github.com/
|
462
|
+
#### [json-duplicate-keys v2024.3.24](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.3.24)
|
440
463
|
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
|
441
464
|
---
|
@@ -0,0 +1,25 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = ["setuptools<70", "wheel"]
|
3
|
+
build-backend = "setuptools.build_meta"
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "json-duplicate-keys"
|
7
|
+
version = "2025.8.19"
|
8
|
+
description = "Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys"
|
9
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
10
|
+
license = { file = "LICENSE" }
|
11
|
+
keywords = ["TPCyberSec", "json", "duplicate keys", "json duplicate keys", "flatten", "unflatten"]
|
12
|
+
classifiers = [
|
13
|
+
"Programming Language :: Python :: 3",
|
14
|
+
"Programming Language :: Python :: Implementation :: Jython"
|
15
|
+
]
|
16
|
+
|
17
|
+
authors = [
|
18
|
+
{ name = "TP Cyber Security", email = "tpcybersec2023@gmail.com" }
|
19
|
+
]
|
20
|
+
|
21
|
+
[project.urls]
|
22
|
+
Homepage = "https://github.com/tpcybersec/json-duplicate-keys"
|
23
|
+
|
24
|
+
[tool.setuptools]
|
25
|
+
packages = ["json_duplicate_keys"]
|
@@ -1 +0,0 @@
|
|
1
|
-
include requirements.txt
|
File without changes
|
@@ -1,22 +0,0 @@
|
|
1
|
-
from json_duplicate_keys import json_duplicate_keys_VERSION
|
2
|
-
import setuptools
|
3
|
-
|
4
|
-
setuptools.setup(
|
5
|
-
name="json-duplicate-keys",
|
6
|
-
version=json_duplicate_keys_VERSION,
|
7
|
-
author="TP Cyber Security",
|
8
|
-
license="MIT",
|
9
|
-
author_email="tpcybersec2023@gmail.com",
|
10
|
-
description="Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys",
|
11
|
-
long_description=open("README.md").read(),
|
12
|
-
long_description_content_type="text/markdown",
|
13
|
-
install_requires=open("requirements.txt").read().split(),
|
14
|
-
url="https://github.com/truocphan/json-duplicate-keys",
|
15
|
-
classifiers=[
|
16
|
-
"Programming Language :: Python :: 3",
|
17
|
-
"Programming Language :: Python :: 2",
|
18
|
-
"Programming Language :: Python :: Implementation :: Jython"
|
19
|
-
],
|
20
|
-
keywords=["TPCyberSec", "json", "duplicate keys", "json duplicate keys", "flatten", "unflatten"],
|
21
|
-
packages=setuptools.find_packages(),
|
22
|
-
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|