From f74fcea35b932deb6b5d228294595a19e801b4f9 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Tue, 13 May 2025 12:51:58 +0300 Subject: [PATCH] fix: safe json conversion (#3148) --- lnbits/db.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lnbits/db.py b/lnbits/db.py index 6b25f4b53..f362f30ee 100644 --- a/lnbits/db.py +++ b/lnbits/db.py @@ -648,9 +648,9 @@ def model_to_dict(model: BaseModel) -> dict: def dict_to_submodel(model: type[TModel], value: dict | str) -> TModel | None: """convert a dictionary or JSON string to a Pydantic model""" if isinstance(value, str): - if value == "null": + if value == "null" or value == "": return None - _subdict = json.loads(value) + _subdict = _safe_load_json(value) elif isinstance(value, dict): _subdict = value @@ -674,7 +674,7 @@ def dict_to_model(_row: dict, model: type[TModel]) -> TModel: type_ = model.__fields__[key].type_ outertype_ = model.__fields__[key].outer_type_ if get_origin(outertype_) is list: - _items = json.loads(value) if isinstance(value, str) else value + _items = _safe_load_json(value) if isinstance(value, str) else value _dict[key] = [ dict_to_submodel(type_, v) if issubclass(type_, BaseModel) else v for v in _items @@ -695,7 +695,7 @@ def dict_to_model(_row: dict, model: type[TModel]) -> TModel: # TODO: remove this when all sub models are migrated to Pydantic # NOTE: this is for type dict on BaseModel, (used in Payment class) if type_ is dict and value: - _dict[key] = json.loads(value) + _dict[key] = _safe_load_json(value) continue _dict[key] = value continue @@ -703,3 +703,12 @@ def dict_to_model(_row: dict, model: type[TModel]) -> TModel: if isinstance(_model, BaseModel): _model.__init__(**_dict) # type: ignore return _model + + +def _safe_load_json(value: str) -> dict: + try: + return json.loads(value) + except json.JSONDecodeError: + # DB is corrupted if it gets here + logger.error(f"Failed to decode JSON: '{value}'") + return {}