Fix: Add robust JSON parsing for V3 query params and fix missing Any import causing startup failure.

This commit is contained in:
Scott Idem
2026-01-02 20:24:51 -05:00
parent 09ec231303
commit 53d252b23d

View File

@@ -1,5 +1,5 @@
from fastapi import APIRouter, Depends, Header, HTTPException, Path, Query, Request, Response, status from fastapi import APIRouter, Depends, Header, HTTPException, Path, Query, Request, Response, status
from typing import Dict, List, Optional, Set, Union from typing import Any, Dict, List, Optional, Set, Union
import json import json
import urllib.parse import urllib.parse
import time import time
@@ -22,6 +22,19 @@ from app.db_sql import redis_lookup_id_random, sql_select, sql_insert, sql_updat
router = APIRouter() router = APIRouter()
def safe_json_loads(json_str: Optional[str]) -> Any:
"""
Safely load a JSON string, handling 'undefined' or invalid formats
common in frontend URL parameters.
"""
if not json_str or json_str == 'undefined':
return None
try:
return json.loads(json_str)
except (json.JSONDecodeError, TypeError) as e:
log.warning(f"Failed to parse JSON string: {json_str}. Error: {e}")
return None
@router.get("/health", response_model=Resp_Body_Base) @router.get("/health", response_model=Resp_Body_Base)
async def health_check( async def health_check(
delay: DelayParams = Depends(get_delay_params), delay: DelayParams = Depends(get_delay_params),
@@ -132,15 +145,9 @@ async def get_obj_li(
and_like_dict_obj = None and_like_dict_obj = None
or_like_dict_obj = None or_like_dict_obj = None
and_in_dict_li_obj = None and_in_dict_li_obj = None
jp_obj = None
jp_obj = safe_json_loads(urllib.parse.unquote(jp)) if jp else None
if jp: if jp_obj:
try:
jp_obj = json.loads(urllib.parse.unquote(jp))
except Exception as e:
log.warning(e)
return mk_resp(data=False, status_code=400, response=response, status_message='The JSON string was not formatted correctly.')
if jp_obj.get('qry'): if jp_obj.get('qry'):
qry_dict_li = jp_obj['qry'] qry_dict_li = jp_obj['qry']
if jp_obj.get('ft_qry'): if jp_obj.get('ft_qry'):
@@ -154,8 +161,7 @@ async def get_obj_li(
if jp_obj.get('and_in_li'): if jp_obj.get('and_in_li'):
and_in_dict_li_obj = jp_obj['and_in_li'] and_in_dict_li_obj = jp_obj['and_in_li']
if order_by_li: order_by_li = safe_json_loads(order_by_li)
order_by_li = json.loads(order_by_li)
obj_name = obj_type_l1 obj_name = obj_type_l1
if obj_name not in obj_type_kv_li: if obj_name not in obj_type_kv_li:
@@ -253,8 +259,7 @@ async def search_obj_li(
log.setLevel(logging.WARNING) log.setLevel(logging.WARNING)
log.debug(locals()) log.debug(locals())
if order_by_li: order_by_li = safe_json_loads(order_by_li)
order_by_li = json.loads(order_by_li)
obj_name = obj_type_l1 obj_name = obj_type_l1
if obj_name not in obj_type_kv_li: if obj_name not in obj_type_kv_li:
@@ -521,15 +526,9 @@ async def get_child_obj_li(
and_like_dict_obj = None and_like_dict_obj = None
or_like_dict_obj = None or_like_dict_obj = None
and_in_dict_li_obj = None and_in_dict_li_obj = None
jp_obj = None
jp_obj = safe_json_loads(urllib.parse.unquote(jp)) if jp else None
if jp: if jp_obj:
try:
jp_obj = json.loads(urllib.parse.unquote(jp))
except Exception as e:
log.warning(e)
return mk_resp(data=False, status_code=400, response=response, status_message='The JSON string was not formatted correctly.')
if jp_obj.get('qry'): if jp_obj.get('qry'):
qry_dict_li = jp_obj['qry'] qry_dict_li = jp_obj['qry']
if jp_obj.get('ft_qry'): if jp_obj.get('ft_qry'):
@@ -543,8 +542,7 @@ async def get_child_obj_li(
if jp_obj.get('and_in_li'): if jp_obj.get('and_in_li'):
and_in_dict_li_obj = jp_obj['and_in_li'] and_in_dict_li_obj = jp_obj['and_in_li']
if order_by_li: order_by_li = safe_json_loads(order_by_li)
order_by_li = json.loads(order_by_li)
obj_name = child_obj_type obj_name = child_obj_type
if obj_name not in obj_type_kv_li: if obj_name not in obj_type_kv_li: