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

+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:
defaults_dict: JsonType = dict(defaults)
if path.exists():
with open(path, 'r', encoding="utf8") as file:
combined: JsonType = _remove_missing(json.load(file, object_hook=_deserialize))
if merge:
merge_json(combined, defaults_dict)
else:
combined = defaults_dict
new_path: Path = path.with_name(f"{path.name}.new")
combined: JsonType | None = None
# try new file first
if new_path.exists():
try:
with new_path.open('r', encoding="utf8") as file:
combined = _remove_missing(json.load(file, object_hook=_deserialize))
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)
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)
new_path.replace(path)
def webopen(url: URL | str):