44
55from dataclasses import dataclass
66from enum import Enum
7- from typing import Any , Callable , Dict , Iterator , List , Optional
7+ from typing import Any , Callable , Dict , Iterator , List , Optional , Union
8+
9+
10+ JSONValue = Union [None , bool , int , float , str , List ["JSONValue" ], Dict [str , "JSONValue" ]]
811
912
1013class PaginationStrategy (str , Enum ):
@@ -29,7 +32,7 @@ class PaginationStep:
2932
3033 payload : Any
3134 params : Dict [str , Any ]
32- cursor : Optional [str ] = None
35+ cursor : Optional [JSONValue ] = None
3336
3437
3538@dataclass
@@ -108,7 +111,7 @@ def cursor_iterator(
108111 fetch_page : Callable [[Dict [str , Any ]], Any ],
109112 * ,
110113 cursor_param : str = "cursor" ,
111- initial_cursor : Optional [str ] = None ,
114+ initial_cursor : Optional [JSONValue ] = None ,
112115 next_cursor_key : str = "next_cursor" ,
113116 max_pages : Optional [int ] = None ,
114117 results_key : Optional [str ] = None ,
@@ -182,11 +185,28 @@ def _extract_items(page: Any, results_key: Optional[str]) -> Optional[List[Any]]
182185 return None
183186
184187
185- def _extract_next_cursor (page : Any , next_cursor_key : str ) -> Optional [str ]:
188+ def _extract_next_cursor (page : Any , next_cursor_key : str ) -> Optional [JSONValue ]:
186189 """Extract the cursor value from a response payload."""
187190
188191 if isinstance (page , dict ):
189192 cursor = page .get (next_cursor_key )
190- if isinstance (cursor , str ) or cursor is None :
193+ if cursor is None :
194+ return None
195+ if _is_json_serializable (cursor ):
191196 return cursor
192197 return None
198+
199+
200+ def _is_json_serializable (value : Any ) -> bool :
201+ """Check whether a value can be represented as JSON."""
202+
203+ if value is None or isinstance (value , (str , int , float , bool )):
204+ return True
205+
206+ if isinstance (value , list ):
207+ return all (_is_json_serializable (item ) for item in value )
208+
209+ if isinstance (value , dict ):
210+ return all (isinstance (key , str ) and _is_json_serializable (item ) for key , item in value .items ())
211+
212+ return False
0 commit comments