Skip to content

Commit b0cf30d

Browse files
bolkedebruinWillAyd
andcommitted
Fix TypeError when pulling field that is None
If normalizing a jsonstruct a field can be set to None due to a schema change. Co-Authored-By: William Ayd <[email protected]>
1 parent facd756 commit b0cf30d

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

doc/source/whatsnew/v1.0.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ I/O
774774
- Bug in :func:`read_json` where default encoding was not set to ``utf-8`` (:issue:`29565`)
775775
- Bug in :class:`PythonParser` where str and bytes were being mixed when dealing with the decimal field (:issue:`29650`)
776776
- :meth:`read_gbq` now accepts ``progress_bar_type`` to display progress bar while the data downloads. (:issue:`29857`)
777-
-
777+
- Bug in :func:`pandas.io.json.json_normalize` where a missing value in the location specified by `record_path` would raise a ``TypeError`` (:issue:`30148`)
778778

779779
Plotting
780780
^^^^^^^^

pandas/io/json/_normalize.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pandas._libs.writers import convert_json_to_lines
1111

1212
from pandas import DataFrame
13+
from pandas.api.types import is_integer, is_scalar
1314

1415

1516
def convert_to_line_delimits(s):
@@ -234,7 +235,10 @@ def _pull_field(js, spec):
234235
for field in spec:
235236
result = result[field]
236237
else:
237-
result = result[spec]
238+
try:
239+
result = result[spec]
240+
except TypeError:
241+
result = None
238242

239243
return result
240244

@@ -286,12 +290,15 @@ def _recursive_extract(data, path, seen_meta, level=0):
286290
else:
287291
for obj in data:
288292
recs = _pull_field(obj, path[0])
289-
recs = [
290-
nested_to_record(r, sep=sep, max_level=max_level)
291-
if isinstance(r, dict)
292-
else r
293-
for r in recs
294-
]
293+
if not is_scalar(recs):
294+
recs = [
295+
nested_to_record(r, sep=sep, max_level=max_level)
296+
if isinstance(r, dict)
297+
else r
298+
for r in recs
299+
]
300+
else:
301+
recs = []
295302

296303
# For repeating the metadata later
297304
lengths.append(len(recs))

pandas/tests/io/json/test_normalize.py

+13
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,19 @@ def test_nested_flattening_consistent(self):
463463
# They should be the same.
464464
tm.assert_frame_equal(df1, df2)
465465

466+
def test_nonetype_record_path(self, nulls_fixture):
467+
# see gh-30148
468+
# should not raise TypeError
469+
df1 = json_normalize(
470+
[
471+
{"state": "Texas", "info": nulls_fixture},
472+
{"state": "Florida", "info": [{"i": 2}]},
473+
],
474+
record_path=["info"],
475+
)
476+
df2 = DataFrame({"i": 2}, index=[0])
477+
tm.assert_equal(df1, df2)
478+
466479

467480
class TestNestedToRecord:
468481
def test_flat_stays_flat(self):

0 commit comments

Comments
 (0)