Skip to content

Commit c8c62b9

Browse files
committed
Released json-duplicate-keys v2024.12.12
1 parent 7d0e005 commit c8c62b9

File tree

3 files changed

+88
-33
lines changed

3 files changed

+88
-33
lines changed

README.md

+39-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
Flatten/ Unflatten and Load(s)/ Dump(s) JSON File/ Object with Duplicate Keys
33

44
<p align="center">
5-
<a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
5+
<a href="https://github.com/truocphan/json-duplicate-keys/releases/"><img src="https://img.shields.io/github/release/truocphan/json-duplicate-keys" height=30></a>
66
<a href="#"><img src="https://img.shields.io/github/downloads/truocphan/json-duplicate-keys/total" height=30></a>
77
<a href="#"><img src="https://img.shields.io/github/stars/truocphan/json-duplicate-keys" height=30></a>
88
<a href="#"><img src="https://img.shields.io/github/forks/truocphan/json-duplicate-keys" height=30></a>
99
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aopen+is%3Aissue"><img src="https://img.shields.io/github/issues/truocphan/json-duplicate-keys" height=30></a>
1010
<a href="https://github.com/truocphan/json-duplicate-keys/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/truocphan/json-duplicate-keys" height=30></a>
11+
<br>
12+
<a href="#"><img src="https://img.shields.io/pypi/v/json-duplicate-keys" height=30></a>
13+
<a href="#"><img src="https://img.shields.io/pypi/dm/json-duplicate-keys" height=30></a>
1114
</p>
1215

1316
## Installation
@@ -107,13 +110,13 @@ Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "relea
107110
JDKSObject = jdks.loads(Jstr)
108111

109112
print(JDKSObject.get("version{{{_2_}}}"))
110-
# OUTPUT: latest
113+
# OUTPUT: {'name': 'version{{{_2_}}}', 'value': 'latest'}
111114

112115
print(JDKSObject.get("release||$0$"))
113-
# OUTPUT: {'version': 'latest'}
116+
# OUTPUT: {'name': 'release||$0$', 'value': {'version': 'latest'}}
114117

115118
print(JDKSObject.get("snapshot||author"))
116-
# OUTPUT: truocphan
119+
# OUTPUT: {'name': 'snapshot||author', 'value': 'truocphan'}
117120
```
118121
---
119122

@@ -182,6 +185,35 @@ print(JDKSObject.getObject())
182185
```
183186
---
184187

188+
### JSON_DUPLICATE_KEYS.insert(`name`, `value`, `position`=None, `case_insensitive`=False, `separator`="||", `parse_index`="$", `dupSign_start`="{{{", `dupSign_end`="}}}", `_isDebug_`=False)
189+
_Insert `value` at `position` in value list of `name`_
190+
- `name`: the key name of the JSON object. Supported flatten key name format
191+
- `value`: new value for key `name`
192+
- `position`: position of the `value` to insert (default insert at the last position of the list)
193+
- `case_insensitive`: the key name case (in)sensitive
194+
- `separator`:
195+
- `parse_index`:
196+
- `dupSign_start`:
197+
- `dupSign_end`:
198+
- `_isDebug_`: Show/ Hide debug error messages
199+
```python
200+
import json_duplicate_keys as jdks
201+
202+
Jstr = '{"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
203+
204+
JDKSObject = jdks.loads(Jstr)
205+
206+
print(JDKSObject.getObject())
207+
# OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
208+
209+
JDKSObject.insert("release", {'version': '2025.1.1'})
210+
JDKSObject.insert("snapshot||release", {'version': '2025.1.1'}, 0)
211+
212+
print(JDKSObject.getObject())
213+
# 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'}]}}
214+
```
215+
---
216+
185217
### 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)
186218
_Update new `value` for existing `name` or Set a new `name` in the JSON object_
187219
- `name`: the key name of the JSON object. Supported flatten key name format
@@ -382,6 +414,9 @@ print(JDKSObject.getObject())
382414
---
383415

384416
## CHANGELOG
417+
#### [json-duplicate-keys v2024.12.12](https://github.com/truocphan/json-duplicate-keys/tree/2024.12.12)
418+
- **New**: _insert_ function
419+
385420
#### [json-duplicate-keys v2024.11.28](https://github.com/truocphan/json-duplicate-keys/tree/2024.11.28)
386421
- **Fixed**: Add subkey name to empty dict of existing key name
387422

json_duplicate_keys/__init__.py

+48-28
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
except NameError:
55
unicode = str # Python 3
66

7+
from collections import OrderedDict
8+
import json, re, copy
9+
710
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
811
# # # # # # # # # # # Normalize Key name # # # # # # # # # # #
912
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
1013
def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False):
11-
import re
12-
1314
# User input data type validation
1415
if type(_isDebug_) != bool: _isDebug_ = False
1516

@@ -31,9 +32,6 @@ def normalize_key(name, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False)
3132
# # # # # # # # # # # # # # # loads # # # # # # # # # # # # # #
3233
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
3334
def loads(Jstr, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
34-
import json, re
35-
from collections import OrderedDict
36-
3735
# User input data type validation
3836
if type(_isDebug_) != bool: _isDebug_ = False
3937

@@ -169,7 +167,6 @@ def load(Jfilepath, dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False,
169167
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
170168
class JSON_DUPLICATE_KEYS:
171169
def __init__(self, Jobj):
172-
from collections import OrderedDict
173170
self.__Jobj = dict()
174171
if type(Jobj) in [dict, OrderedDict, list]:
175172
self.__Jobj = Jobj
@@ -188,9 +185,6 @@ def getObject(self):
188185
# # # # # # # # # # # # # # # get # # # # # # # # # # # # # # #
189186
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
190187
def get(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
191-
import re
192-
from collections import OrderedDict
193-
194188
# User input data type validation
195189
if type(_isDebug_) != bool: _isDebug_ = False
196190

@@ -247,9 +241,6 @@ def get(self, name, case_insensitive=False, separator="||", parse_index="$", _is
247241
# # # # # # # # # # # # # # # set # # # # # # # # # # # # # # #
248242
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
249243
def set(self, name, value, case_insensitive=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
250-
import re
251-
from collections import OrderedDict
252-
253244
# User input data type validation
254245
if type(_isDebug_) != bool: _isDebug_ = False
255246

@@ -329,12 +320,55 @@ def set(self, name, value, case_insensitive=False, separator="||", parse_index="
329320
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
330321

331322

323+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
324+
# # # # # # # # # # # # # # insert # # # # # # # # # # # # # #
325+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
326+
def insert(self, name, value, position=None, case_insensitive=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False):
327+
# User input data type validation
328+
if type(_isDebug_) != bool: _isDebug_ = False
329+
330+
if type(name) not in [str, unicode]:
331+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the KEY name must be str or unicode, not {}\x1b[0m".format(type(name)))
332+
return False
333+
334+
if type(position) != int: position = None
335+
336+
if type(case_insensitive) != bool: case_insensitive = False
337+
338+
if type(separator) not in [str, unicode]: separator = "||"
339+
340+
if type(parse_index) not in [str, unicode]: parse_index = "$"
341+
342+
if type(dupSign_start) not in [str, unicode]: dupSign_start = "{{{"
343+
344+
if type(dupSign_end) not in [str, unicode]: dupSign_end = "}}}"
345+
346+
if type(self.getObject()) not in [list, dict, OrderedDict]:
347+
if _isDebug_: print("\x1b[31m[-] DataTypeError: the JSON object must be list, dict or OrderedDict, not {}\x1b[0m".format(type(self.getObject())))
348+
return False
349+
350+
if re.search(re.escape(separator)+"$", name):
351+
if _isDebug_: print("\x1b[31m[-] KeyNameInvalidError: \x1b[0m"+name)
352+
return False
353+
354+
Jget = self.get(name, case_insensitive=case_insensitive, separator=separator, parse_index=parse_index, _isDebug_=_isDebug_)
355+
356+
if Jget["value"] != "JSON_DUPLICATE_KEYS_ERROR":
357+
if type(Jget["value"]) == list:
358+
if position == None: position = len(Jget["value"])
359+
360+
Jget["value"].insert(position, value)
361+
362+
return self.update(Jget["name"], Jget["value"], separator=separator, parse_index=parse_index, dupSign_start=dupSign_start, dupSign_end=dupSign_end, _isDebug_=_isDebug_)
363+
else:
364+
if _isDebug_: print("\x1b[31m[-] DataTypeError: The data type of {} must be list, not {}\x1b[0m".format(Jget["name"], type(Jget["value"])))
365+
return False
366+
367+
332368
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
333369
# # # # # # # # # # # # # # update # # # # # # # # # # # # # #
334370
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
335371
def update(self, name, value, case_insensitive=False, allow_new_key=False, separator="||", parse_index="$", dupSign_start="{{{", dupSign_end="}}}", ordered_dict=False, _isDebug_=False):
336-
import re
337-
338372
# User input data type validation
339373
if type(_isDebug_) != bool: _isDebug_ = False
340374

@@ -379,8 +413,6 @@ def update(self, name, value, case_insensitive=False, allow_new_key=False, separ
379413
# # # # # # # # # # # # # # delete # # # # # # # # # # # # #
380414
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
381415
def delete(self, name, case_insensitive=False, separator="||", parse_index="$", _isDebug_=False):
382-
import re
383-
384416
# User input data type validation
385417
if type(_isDebug_) != bool: _isDebug_ = False
386418

@@ -420,8 +452,6 @@ def delete(self, name, case_insensitive=False, separator="||", parse_index="$",
420452
# # # # # # # # # # # # filter_keys # # # # # # # # # # # # #
421453
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
422454
def filter_keys(self, name, separator="||", parse_index="$", ordered_dict=False):
423-
import re, copy
424-
425455
JDKSObject = copy.deepcopy(self)
426456
JDKSObject.flatten(separator=separator, parse_index=parse_index, ordered_dict=ordered_dict)
427457
newJDKSObject = loads("{}", ordered_dict=ordered_dict)
@@ -444,8 +474,6 @@ def filter_keys(self, name, separator="||", parse_index="$", ordered_dict=False)
444474
# # # # # # # # # # # # filter_values # # # # # # # # # # # # #
445475
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
446476
def filter_values(self, value, separator="||", parse_index="$", ordered_dict=False):
447-
import re, copy
448-
449477
JDKSObject = copy.deepcopy(self)
450478
JDKSObject.flatten(separator=separator, parse_index=parse_index, ordered_dict=ordered_dict)
451479
newJDKSObject = loads("{}", ordered_dict=ordered_dict)
@@ -468,9 +496,6 @@ def filter_values(self, value, separator="||", parse_index="$", ordered_dict=Fal
468496
# # # # # # # # # # # # # # dumps # # # # # # # # # # # # # #
469497
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
470498
def dumps(self, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=False, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False):
471-
import json, re
472-
from collections import OrderedDict
473-
474499
# User input data type validation
475500
if type(_isDebug_) != bool: _isDebug_ = False
476501

@@ -514,8 +539,6 @@ def dump(self, Jfilepath, dupSign_start="{{{", dupSign_end="}}}", _isDebug_=Fals
514539
# # # # # # # # # # # # # flatten # # # # # # # # # # # # # #
515540
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
516541
def flatten(self, separator="||", parse_index="$", ordered_dict=False, _isDebug_=False):
517-
from collections import OrderedDict
518-
519542
# User input data type validation
520543
if type(_isDebug_) != bool: _isDebug_ = False
521544

@@ -575,9 +598,6 @@ def __convert_Jobj_to_Jflat(Jobj, key=None):
575598
# # # # # # # # # # # # # unflatten # # # # # # # # # # # # #
576599
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
577600
def unflatten(self, separator="||", parse_index="$", ordered_dict=False, _isDebug_=False):
578-
import re
579-
from collections import OrderedDict
580-
581601
# User input data type validation
582602
if type(_isDebug_) != bool: _isDebug_ = False
583603

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setuptools.setup(
44
name="json-duplicate-keys",
5-
version="2024.11.28",
5+
version="2024.12.12",
66
author="TP Cyber Security",
77
license="MIT",
88
author_email="[email protected]",

0 commit comments

Comments
 (0)