Implement a more robust JSON save-load cycle

This commit is contained in:
DevilXD committed 2026-05-25 21:20:09 +02:00
1 parent 988889c82e
commit 184abe2cbf
2 files changed
+23 -9

No files matched your search

+1
View File
@@ -9,6 +9,7 @@ __pycache__
/*.tmp /*.tmp
/Twitch Drops Miner /Twitch Drops Miner
# Dev files # Dev files
*.new
/env /env
/cache /cache
/*.jar /*.jar
+22 -9
View File
@@ -242,20 +242,33 @@ def merge_json(obj: JsonType, template: Mapping[Any, Any]) -> None:
def json_load(path: Path, defaults: _JSON_T, *, merge: bool = True) -> _JSON_T: def json_load(path: Path, defaults: _JSON_T, *, merge: bool = True) -> _JSON_T:
defaults_dict: JsonType = dict(defaults) new_path: Path = path.with_name(f"{path.name}.new")
if path.exists(): combined: JsonType | None = None
with open(path, 'r', encoding="utf8") as file: # try new file first
combined: JsonType = _remove_missing(json.load(file, object_hook=_deserialize)) if new_path.exists():
if merge: try:
merge_json(combined, defaults_dict) with new_path.open('r', encoding="utf8") as file:
else: combined = _remove_missing(json.load(file, object_hook=_deserialize))
combined = defaults_dict except json.JSONDecodeError:
# remove invalid file
new_path.unlink()
# try the old file
if combined is None and path.exists():
with path.open('r', encoding="utf8") as file:
combined = _remove_missing(json.load(file, object_hook=_deserialize))
# handle defaults and merging
if combined is None:
combined = dict(defaults) # always make a copy of defaults
elif merge:
merge_json(combined, dict(defaults))
return cast(_JSON_T, combined) return cast(_JSON_T, combined)
def json_save(path: Path, contents: Mapping[Any, Any], *, sort: bool = False) -> None: def json_save(path: Path, contents: Mapping[Any, Any], *, sort: bool = False) -> None:
with open(path, 'w', encoding="utf8") as file: new_path: Path = path.with_name(f"{path.name}.new")
with new_path.open('w', encoding="utf8") as file:
json.dump(contents, file, default=_serialize, sort_keys=sort, indent=4) json.dump(contents, file, default=_serialize, sort_keys=sort, indent=4)
new_path.replace(path)
def webopen(url: URL | str): def webopen(url: URL | str):