Skip to content

Commit 1b5b02c

Browse files
authored
BUG: Fix json_normalize 'meta' validation (#63136)
1 parent 27fdae8 commit 1b5b02c

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,7 @@ I/O
11891189
- Fix bug in ``on_bad_lines`` callable when returning too many fields: now emits
11901190
``ParserWarning`` and truncates extra fields regardless of ``index_col`` (:issue:`61837`)
11911191
- Bug in :func:`pandas.json_normalize` inconsistently handling non-dict items in ``data`` when ``max_level`` was set. The function will now raise a ``TypeError`` if ``data`` is a list containing non-dict items (:issue:`62829`)
1192+
- Bug in :func:`pandas.json_normalize` raising ``TypeError`` when ``meta`` contained a non-string key (e.g., ``int``) and ``record_path`` was specified, which was inconsistent with the behavior when ``record_path`` was ``None`` (:issue:`63019`)
11921193
- Bug in :meth:`.DataFrame.to_json` when ``"index"`` was a value in the :attr:`DataFrame.column` and :attr:`Index.name` was ``None``. Now, this will fail with a ``ValueError`` (:issue:`58925`)
11931194
- Bug in :meth:`.io.common.is_fsspec_url` not recognizing chained fsspec URLs (:issue:`48978`)
11941195
- Bug in :meth:`DataFrame._repr_html_` which ignored the ``"display.float_format"`` option (:issue:`59876`)

pandas/io/json/_normalize.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,37 @@ def _simple_json_normalize(
267267
return normalized_json_object
268268

269269

270+
def _validate_meta(meta: str | list[str | list[str]] | None) -> None:
271+
"""
272+
Validate that meta parameter contains only strings or lists of strings.
273+
Parameters
274+
----------
275+
meta : str or list of str or list of list of str or None
276+
The meta parameter to validate.
277+
Raises
278+
------
279+
TypeError
280+
If meta contains elements that are not strings or lists of strings.
281+
"""
282+
if meta is None:
283+
return
284+
if isinstance(meta, str):
285+
return
286+
for item in meta:
287+
if isinstance(item, list):
288+
for subitem in item:
289+
if not isinstance(subitem, str):
290+
raise TypeError(
291+
"All elements in nested meta paths must be strings. "
292+
f"Found {type(subitem).__name__}: {subitem!r}"
293+
)
294+
elif not isinstance(item, str):
295+
raise TypeError(
296+
"All elements in 'meta' must be strings or lists of strings. "
297+
f"Found {type(item).__name__}: {item!r}"
298+
)
299+
300+
270301
@set_module("pandas")
271302
def json_normalize(
272303
data: dict | list[dict] | Series,
@@ -437,6 +468,7 @@ def json_normalize(
437468
438469
Returns normalized data with columns prefixed with the given string.
439470
"""
471+
_validate_meta(meta)
440472

441473
def _pull_field(
442474
js: dict[str, Any], spec: list | str, extract_record: bool = False

pandas/tests/io/json/test_normalize.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,3 +927,14 @@ def test_series_non_zero_index(self):
927927
index=[1, 2, 3],
928928
)
929929
tm.assert_frame_equal(result, expected)
930+
931+
def test_json_normalize_meta_string_validation(self):
932+
# GH 63019
933+
data = [{"a": 1, 12: "meta_value", "nested": [{"b": 2}]}]
934+
935+
# Test non-string meta raises TypeError consistently
936+
with pytest.raises(TypeError, match="must be strings"):
937+
json_normalize(data, meta=[12])
938+
939+
with pytest.raises(TypeError, match="must be strings"):
940+
json_normalize(data, record_path=["nested"], meta=[12])

0 commit comments

Comments
 (0)