Skip to content

Commit b0b506f

Browse files
committed
Fix the issue: inserting a value with an empty or null name
1 parent f46d023 commit b0b506f

File tree

3 files changed

+65
-43
lines changed

3 files changed

+65
-43
lines changed

README.md

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,34 @@
22
<h1>JSON Duplicate Keys - PyPI</h1>
33
<i>Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys</i>
44
<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>
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>
1111
<br>
1212
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
1313
<a href="#"><img src="https://img.shields.io/pypi/pyversions/json-duplicate-keys" height=30></a>
1414
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
1515
</div>
1616

17-
## Installation
17+
---
18+
# 🛠️ Installation
1819
#### From PyPI:
1920
```console
2021
pip install json-duplicate-keys
2122
```
2223
#### From Source:
2324
```console
24-
git clone https://github.com/tpcybersec/json-duplicate-keys.git --branch <Branch/Tag>
25+
git clone https://github.com/TPCyberSec/json-duplicate-keys.git --branch <Branch/Tag>
2526
cd json-duplicate-keys
2627
python -m build
2728
python -m pip install dist/json_duplicate_keys-<version>-py3-none-any.whl
2829
```
2930

30-
## Basic Usage
31+
---
32+
# 📘 Basic Usage
3133
### normalize_key(`name`, `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
3234
_Normalize Key name_
3335
- `name`: key name
@@ -40,8 +42,8 @@ import json_duplicate_keys as jdks
4042
print(jdks.normalize_key("version{{{_2_}}}"))
4143
# OUTPUT: version
4244
```
43-
---
4445

46+
---
4547
### loads(`Jstr`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
4648
_Deserialize a JSON format string to a class `JSON_DUPLICATE_KEYS`_
4749
- `Jstr`: a JSON format string
@@ -60,8 +62,8 @@ JDKSObject = jdks.loads(Jstr)
6062
print(JDKSObject)
6163
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE987940>
6264
```
63-
---
6465

66+
---
6567
### load(`Jfilepath`, `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `skipDuplicated`=False, `_isDebug_`=False)
6668
_Deserialize a JSON format string from a file to a class `JSON_DUPLICATE_KEYS`_
6769
- `Jfilepath`: The path to the file containing the JSON format string
@@ -82,8 +84,8 @@ JDKSObject = jdks.load(Jfilepath)
8284
print(JDKSObject)
8385
# OUTPUT: <json_duplicate_keys.JSON_DUPLICATE_KEYS object at 0x00000270AE986D40>
8486
```
85-
---
8687

88+
---
8789
### JSON_DUPLICATE_KEYS.getObject()
8890
_Get the JSON object_
8991
```python
@@ -96,8 +98,8 @@ JDKSObject = jdks.loads(Jstr)
9698
print(JDKSObject.getObject())
9799
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
98100
```
99-
---
100101

102+
---
101103
### JSON_DUPLICATE_KEYS.get(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
102104
_Get value in the JSON object by `name`_
103105
- `name`: the key name of the JSON object. Supported flatten key name format
@@ -121,8 +123,8 @@ print(JDKSObject.get("release||$0$"))
121123
print(JDKSObject.get("snapshot||author"))
122124
# OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
123125
```
124-
---
125126

127+
---
126128
### JSON_DUPLICATE_KEYS.set(`name`, `value`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `ordered_dict`=False, `_isDebug_`=False)
127129
_Set a new `name` and `value` for the JSON object_
128130
- `name`: new key name for the JSON object. Supported flat key name format
@@ -167,8 +169,8 @@ JDKSObject.set("snapshot||author", "truocphan")
167169
print(JDKSObject.getObject())
168170
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan'}}
169171
```
170-
---
171172

173+
---
172174
### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
173175
_Insert `value` at `position` in value list of `name`_
174176
- `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)
195197

196198
print(JDKSObject.getObject())
197199
# 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'}]}]
198210
```
199-
---
200211

212+
---
201213
### 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)
202214
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
203215
- `name`: the key name of the JSON object. Supported flatten key name format
@@ -226,8 +238,8 @@ JDKSObject.update("snapshot||version", "latest")
226238
print(JDKSObject.getObject())
227239
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': ['22.3.3', 'latest'], 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': 'latest', 'release': [{'version': 'latest'}]}}
228240
```
229-
---
230241

242+
---
231243
### JSON_DUPLICATE_KEYS.delete(`name`, `case_insensitive`=False, `separator`="||", `parse_index`="$", `_isDebug_`=False)
232244
_Delete a key-value pair in a JSON object by key `name`_
233245
- `name`: the key name of the JSON object. Supported flatten key name format
@@ -252,8 +264,8 @@ JDKSObject.delete("snapshot")
252264
print(JDKSObject.getObject())
253265
# OUTPUT: {'author': 'truocphan', 'version{{{_2_}}}': 'latest', 'release': []}
254266
```
255-
---
256267

268+
---
257269
### JSON_DUPLICATE_KEYS.filter_keys(`name`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
258270
_Return a `JSON_DUPLICATE_KEYS` object with keys matching a pattern_
259271
- `name`:
@@ -273,8 +285,8 @@ print(JDKSObject.filter_keys("version").dumps())
273285
print(JDKSObject.dumps())
274286
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
275287
```
276-
---
277288

289+
---
278290
### JSON_DUPLICATE_KEYS.filter_values(`value`, `separator`="||", `parse_index`="$", `ordered_dict`=False)
279291
_Return a `JSON_DUPLICATE_KEYS` object with values matching a pattern_
280292
- `value`:
@@ -294,8 +306,8 @@ print(JDKSObject.filter_values("latest").dumps())
294306
print(JDKSObject.dumps())
295307
# OUTPUT: {"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}
296308
```
297-
---
298309

310+
---
299311
### 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)
300312
_Serialize a JSON object to a JSON format string_
301313
- `dupSign_start`: Start symbol for marking duplicates (default: `{{{`)
@@ -319,8 +331,8 @@ JDKSObject.delete("snapshot")
319331
print(JDKSObject.dumps())
320332
# OUTPUT: {"author": "truocphan", "version": "latest", "release": []}
321333
```
322-
---
323334

335+
---
324336
### 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)
325337
_Serialize a JSON object to a JSON format string and write to a file_
326338
- `Jfilepath`: the path to the file to save the JSON format string
@@ -349,8 +361,8 @@ JDKSObject_load = jdks.load(Jfilepath)
349361
print(JDKSObject_load.getObject())
350362
# OUTPUT: {'author': 'truocphan', 'version': 'latest', 'release': []}
351363
```
352-
---
353364

365+
---
354366
### JSON_DUPLICATE_KEYS.flatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
355367
_Flatten a JSON object to a single key-value pairs_
356368
- `separator`: Separator for flatten keys (default: `||`)
@@ -372,8 +384,8 @@ JDKSObject.flatten()
372384
print(JDKSObject.getObject())
373385
# 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'}
374386
```
375-
---
376387

388+
---
377389
### JSON_DUPLICATE_KEYS.unflatten(`separator`="||", `parse_index`="$", `ordered_dict`=False, `_isDebug_`=False)
378390
_Unflatten a flattened JSON object back to a JSON object_
379391
- `separator`: Separator for flatten keys (default: `||`)
@@ -395,37 +407,41 @@ JDKSObject.unflatten()
395407
print(JDKSObject.getObject())
396408
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
397409
```
410+
398411
---
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
399415

400-
## CHANGELOG
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
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
404419

405-
#### [json-duplicate-keys v2025.7.1](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.7.1)
406-
- [**Updated**] Fixed some issues when loading JSON strings with `skipDuplicated` option
407-
- [**Updated**] Allow loading of JSON data in byte string format
408-
- [**Updated**] Issue with getting and setting an empty list
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
409424

410-
#### [json-duplicate-keys v2025.6.6](https://github.com/tpcybersec/json-duplicate-keys/tree/2025.6.6)
411-
- [**Updated**] Added `skipDuplicated` parameter to `load` and `loads` functions to improve performance when parsing large JSON strings by skipping duplicate keys.
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.
412427

413-
#### [json-duplicate-keys v2024.12.12](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.12.12)
428+
### [json-duplicate-keys v2024.12.12](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.12.12)
414429
- **New**: _insert_ function
415430

416-
#### [json-duplicate-keys v2024.11.28](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.28)
431+
### [json-duplicate-keys v2024.11.28](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.28)
417432
- **Fixed**: Add subkey name to empty dict of existing key name
418433

419-
#### [json-duplicate-keys v2024.11.19](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.11.19)
434+
### [json-duplicate-keys v2024.11.19](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.11.19)
420435
- **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
421436

422-
#### [json-duplicate-keys v2024.7.17](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.7.17)
437+
### [json-duplicate-keys v2024.7.17](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.7.17)
423438
- **Fixed**: issue #3 break the set function when the key's value is empty. Thanks [ptth222](https://github.com/ptth222) for reporting this issue.
424439

425-
#### [json-duplicate-keys v2024.4.20](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.4.20)
440+
### [json-duplicate-keys v2024.4.20](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.4.20)
426441
- **New**: _filter_values_
427442
- **Updated**: _filter_keys_
428443

429-
#### [json-duplicate-keys v2024.3.24](https://github.com/tpcybersec/json-duplicate-keys/tree/2024.3.24)
444+
### [json-duplicate-keys v2024.3.24](https://github.com/TPCyberSec/json-duplicate-keys/tree/2024.3.24)
430445
- **Updated**: _normalize_key_, _loads_, _get_, _set_, _update_, _delete_
446+
431447
---

json_duplicate_keys/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,8 @@ def insert(self, name, value, position=None, case_insensitive=False, separator="
362362
# User input data type validation
363363
if type(_isDebug_) != bool: _isDebug_ = False
364364

365-
if type(name) not in [str, unicode]:
366-
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
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)))
367367
return False
368368

369369
if type(position) != int: position = None
@@ -381,6 +381,12 @@ def insert(self, name, value, position=None, case_insensitive=False, separator="
381381
if type(self.getObject()) not in [list, dict, OrderedDict]:
382382
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
383383
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
384390

385391
if re.search(re.escape(separator)+"$", name):
386392
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "json-duplicate-keys"
77
version = "2025.8.19"
88
description = "Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys"
99
readme = { file = "README.md", content-type = "text/markdown" }
10-
license = { file = "LICENSE" }
10+
license = { text = "MIT" }
1111
keywords = ["TPCyberSec", "json", "duplicate keys", "json duplicate keys", "flatten", "unflatten"]
1212
classifiers = [
1313
"Programming Language :: Python :: 3",
@@ -19,7 +19,7 @@ authors = [
1919
]
2020

2121
[project.urls]
22-
Homepage = "https://github.com/tpcybersec/json-duplicate-keys"
22+
Homepage = "https://github.com/TPCyberSec/json-duplicate-keys"
2323

2424
[tool.setuptools]
2525
packages = ["json_duplicate_keys"]

0 commit comments

Comments
 (0)