53 lines
1.7 KiB
Python
53 lines
1.7 KiB
Python
import json
|
|
from json import JSONDecodeError, JSONDecoder
|
|
from typing import Any, Tuple
|
|
|
|
import partial_json_parser
|
|
from partial_json_parser.core.options import Allow
|
|
|
|
|
|
def _find_common_prefix(s1: str, s2: str) -> str:
|
|
prefix = ""
|
|
min_length = min(len(s1), len(s2))
|
|
for i in range(0, min_length):
|
|
if s1[i] == s2[i]:
|
|
prefix += s1[i]
|
|
else:
|
|
break
|
|
return prefix
|
|
|
|
|
|
def _partial_json_loads(input_str: str, flags: Allow) -> Tuple[Any, int]:
|
|
"""
|
|
Parse incomplete or partial JSON strings commonly encountered during streaming.
|
|
|
|
Args:
|
|
input_str (str): The potentially incomplete JSON string to parse.
|
|
flags (Allow): Bitwise flags controlling what types of partial data are allowed.
|
|
Common flags include:
|
|
- Allow.STR: Allow partial strings (e.g., '"hello wo' -> 'hello wo')
|
|
- Allow.OBJ: Allow partial objects (e.g., '{"key":' -> {'key': None})
|
|
- Allow.ARR: Allow partial arrays (e.g., '[1, 2,' -> [1, 2])
|
|
- Allow.ALL: Allow all types of partial data
|
|
|
|
Returns:
|
|
Tuple[Any, int]: A tuple containing:
|
|
- parsed_object: The Python object parsed from the JSON
|
|
- consumed_length: Number of characters consumed from input_str
|
|
"""
|
|
try:
|
|
return (partial_json_parser.loads(input_str, flags), len(input_str))
|
|
except JSONDecodeError as e:
|
|
if "Extra data" in e.msg:
|
|
dec = JSONDecoder()
|
|
return dec.raw_decode(input_str)
|
|
raise
|
|
|
|
|
|
def _is_complete_json(input_str: str) -> bool:
|
|
try:
|
|
json.loads(input_str)
|
|
return True
|
|
except JSONDecodeError:
|
|
return False
|