Skip to content

Commit f56e141

Browse files
authored
TYP: _json.py (#56539)
* TYP: _json.py * fix index special-casing
1 parent 43f3dde commit f56e141

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

pandas/io/json/_json.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Generic,
1515
Literal,
1616
TypeVar,
17+
final,
1718
overload,
1819
)
1920
import warnings
@@ -37,11 +38,11 @@
3738
is_string_dtype,
3839
)
3940
from pandas.core.dtypes.dtypes import PeriodDtype
40-
from pandas.core.dtypes.generic import ABCIndex
4141

4242
from pandas import (
4343
ArrowDtype,
4444
DataFrame,
45+
Index,
4546
MultiIndex,
4647
Series,
4748
isna,
@@ -1119,10 +1120,11 @@ class Parser:
11191120
"us": 31536000000000,
11201121
"ns": 31536000000000000,
11211122
}
1123+
json: str
11221124

11231125
def __init__(
11241126
self,
1125-
json,
1127+
json: str,
11261128
orient,
11271129
dtype: DtypeArg | None = None,
11281130
convert_axes: bool = True,
@@ -1157,7 +1159,8 @@ def __init__(
11571159
self.obj: DataFrame | Series | None = None
11581160
self.dtype_backend = dtype_backend
11591161

1160-
def check_keys_split(self, decoded) -> None:
1162+
@final
1163+
def check_keys_split(self, decoded: dict) -> None:
11611164
"""
11621165
Checks that dict has only the appropriate keys for orient='split'.
11631166
"""
@@ -1166,6 +1169,7 @@ def check_keys_split(self, decoded) -> None:
11661169
bad_keys_joined = ", ".join(bad_keys)
11671170
raise ValueError(f"JSON data had unexpected key(s): {bad_keys_joined}")
11681171

1172+
@final
11691173
def parse(self):
11701174
self._parse()
11711175

@@ -1179,34 +1183,41 @@ def parse(self):
11791183
def _parse(self):
11801184
raise AbstractMethodError(self)
11811185

1186+
@final
11821187
def _convert_axes(self) -> None:
11831188
"""
11841189
Try to convert axes.
11851190
"""
11861191
obj = self.obj
11871192
assert obj is not None # for mypy
11881193
for axis_name in obj._AXIS_ORDERS:
1189-
new_axis, result = self._try_convert_data(
1194+
ax = obj._get_axis(axis_name)
1195+
ser = Series(ax, dtype=ax.dtype, copy=False)
1196+
new_ser, result = self._try_convert_data(
11901197
name=axis_name,
1191-
data=obj._get_axis(axis_name),
1198+
data=ser,
11921199
use_dtypes=False,
11931200
convert_dates=True,
1201+
is_axis=True,
11941202
)
11951203
if result:
1204+
new_axis = Index(new_ser, dtype=new_ser.dtype, copy=False)
11961205
setattr(self.obj, axis_name, new_axis)
11971206

11981207
def _try_convert_types(self):
11991208
raise AbstractMethodError(self)
12001209

1210+
@final
12011211
def _try_convert_data(
12021212
self,
12031213
name: Hashable,
1204-
data,
1214+
data: Series,
12051215
use_dtypes: bool = True,
12061216
convert_dates: bool | list[str] = True,
1207-
):
1217+
is_axis: bool = False,
1218+
) -> tuple[Series, bool]:
12081219
"""
1209-
Try to parse a ndarray like into a column by inferring dtype.
1220+
Try to parse a Series into a column by inferring dtype.
12101221
"""
12111222
# don't try to coerce, unless a force conversion
12121223
if use_dtypes:
@@ -1242,7 +1253,7 @@ def _try_convert_data(
12421253
if result:
12431254
return new_data, True
12441255

1245-
if self.dtype_backend is not lib.no_default and not isinstance(data, ABCIndex):
1256+
if self.dtype_backend is not lib.no_default and not is_axis:
12461257
# Fall through for conversion later on
12471258
return data, True
12481259
elif is_string_dtype(data.dtype):
@@ -1285,7 +1296,8 @@ def _try_convert_data(
12851296

12861297
return data, True
12871298

1288-
def _try_convert_to_date(self, data):
1299+
@final
1300+
def _try_convert_to_date(self, data: Series) -> tuple[Series, bool]:
12891301
"""
12901302
Try to parse a ndarray like into a date column.
12911303
@@ -1335,13 +1347,11 @@ def _try_convert_to_date(self, data):
13351347
return new_data, True
13361348
return data, False
13371349

1338-
def _try_convert_dates(self):
1339-
raise AbstractMethodError(self)
1340-
13411350

13421351
class SeriesParser(Parser):
13431352
_default_orient = "index"
13441353
_split_keys = ("name", "index", "data")
1354+
obj: Series | None
13451355

13461356
def _parse(self) -> None:
13471357
data = ujson_loads(self.json, precise_float=self.precise_float)
@@ -1366,6 +1376,7 @@ def _try_convert_types(self) -> None:
13661376
class FrameParser(Parser):
13671377
_default_orient = "columns"
13681378
_split_keys = ("columns", "index", "data")
1379+
obj: DataFrame | None
13691380

13701381
def _parse(self) -> None:
13711382
json = self.json
@@ -1403,20 +1414,24 @@ def _parse(self) -> None:
14031414
ujson_loads(json, precise_float=self.precise_float), dtype=None
14041415
)
14051416

1406-
def _process_converter(self, f, filt=None) -> None:
1417+
def _process_converter(
1418+
self,
1419+
f: Callable[[Hashable, Series], tuple[Series, bool]],
1420+
filt: Callable[[Hashable], bool] | None = None,
1421+
) -> None:
14071422
"""
14081423
Take a conversion function and possibly recreate the frame.
14091424
"""
14101425
if filt is None:
1411-
filt = lambda col, c: True
1426+
filt = lambda col: True
14121427

14131428
obj = self.obj
14141429
assert obj is not None # for mypy
14151430

14161431
needs_new_obj = False
14171432
new_obj = {}
14181433
for i, (col, c) in enumerate(obj.items()):
1419-
if filt(col, c):
1434+
if filt(col):
14201435
new_data, result = f(col, c)
14211436
if result:
14221437
c = new_data
@@ -1453,6 +1468,10 @@ def is_ok(col) -> bool:
14531468
"""
14541469
Return if this col is ok to try for a date parse.
14551470
"""
1471+
if col in convert_dates:
1472+
return True
1473+
if not self.keep_default_dates:
1474+
return False
14561475
if not isinstance(col, str):
14571476
return False
14581477

@@ -1467,9 +1486,4 @@ def is_ok(col) -> bool:
14671486
return True
14681487
return False
14691488

1470-
self._process_converter(
1471-
lambda col, c: self._try_convert_to_date(c),
1472-
lambda col, c: (
1473-
(self.keep_default_dates and is_ok(col)) or col in convert_dates
1474-
),
1475-
)
1489+
self._process_converter(lambda col, c: self._try_convert_to_date(c), filt=is_ok)

0 commit comments

Comments
 (0)