diff --git a/doc/redirects.csv b/doc/redirects.csv index 587a5e9f65b38..0a71f037d23c3 100644 --- a/doc/redirects.csv +++ b/doc/redirects.csv @@ -777,7 +777,7 @@ generated/pandas.io.formats.style.Styler.to_excel,../reference/api/pandas.io.for generated/pandas.io.formats.style.Styler.use,../reference/api/pandas.io.formats.style.Styler.use generated/pandas.io.formats.style.Styler.where,../reference/api/pandas.io.formats.style.Styler.where generated/pandas.io.json.build_table_schema,../reference/api/pandas.io.json.build_table_schema -generated/pandas.io.json.json_normalize,../reference/api/pandas.io.json.json_normalize +generated/pandas.io.json.json_normalize,../reference/api/pandas.json_normalize generated/pandas.io.stata.StataReader.data_label,../reference/api/pandas.io.stata.StataReader.data_label generated/pandas.io.stata.StataReader.value_labels,../reference/api/pandas.io.stata.StataReader.value_labels generated/pandas.io.stata.StataReader.variable_labels,../reference/api/pandas.io.stata.StataReader.variable_labels diff --git a/doc/source/reference/io.rst b/doc/source/reference/io.rst index 50168dec928ab..0037d4a4410c3 100644 --- a/doc/source/reference/io.rst +++ b/doc/source/reference/io.rst @@ -50,13 +50,13 @@ JSON :toctree: api/ read_json + json_normalize .. currentmodule:: pandas.io.json .. autosummary:: :toctree: api/ - json_normalize build_table_schema .. currentmodule:: pandas diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index 52e16c15fc481..ae0f02312e1df 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -2136,27 +2136,26 @@ into a flat table. .. ipython:: python - from pandas.io.json import json_normalize data = [{'id': 1, 'name': {'first': 'Coleen', 'last': 'Volk'}}, {'name': {'given': 'Mose', 'family': 'Regner'}}, {'id': 2, 'name': 'Faye Raker'}] - json_normalize(data) + pd.json_normalize(data) .. ipython:: python data = [{'state': 'Florida', 'shortname': 'FL', 'info': {'governor': 'Rick Scott'}, - 'counties': [{'name': 'Dade', 'population': 12345}, - {'name': 'Broward', 'population': 40000}, - {'name': 'Palm Beach', 'population': 60000}]}, + 'county': [{'name': 'Dade', 'population': 12345}, + {'name': 'Broward', 'population': 40000}, + {'name': 'Palm Beach', 'population': 60000}]}, {'state': 'Ohio', 'shortname': 'OH', 'info': {'governor': 'John Kasich'}, - 'counties': [{'name': 'Summit', 'population': 1234}, - {'name': 'Cuyahoga', 'population': 1337}]}] + 'county': [{'name': 'Summit', 'population': 1234}, + {'name': 'Cuyahoga', 'population': 1337}]}] - json_normalize(data, 'counties', ['state', 'shortname', ['info', 'governor']]) + pd.json_normalize(data, 'county', ['state', 'shortname', ['info', 'governor']]) The max_level parameter provides more control over which level to end normalization. With max_level=1 the following snippet normalizes until 1st nesting level of the provided dict. @@ -2169,7 +2168,7 @@ With max_level=1 the following snippet normalizes until 1st nesting level of the 'Name': 'Name001'}}, 'Image': {'a': 'b'} }] - json_normalize(data, max_level=1) + pd.json_normalize(data, max_level=1) .. _io.jsonl: diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index be137eaabd40a..b6b91983b8267 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -170,7 +170,7 @@ which level to end normalization (:issue:`23843`): The repr now looks like this: -.. ipython:: python +.. code-block:: ipython from pandas.io.json import json_normalize data = [{ diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst old mode 100755 new mode 100644 index 7554a2fc0b1c2..6ad6b5129ef5a --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -498,6 +498,9 @@ Deprecations - The parameter ``numeric_only`` of :meth:`Categorical.min` and :meth:`Categorical.max` is deprecated and replaced with ``skipna`` (:issue:`25303`) - The parameter ``label`` in :func:`lreshape` has been deprecated and will be removed in a future version (:issue:`29742`) - ``pandas.core.index`` has been deprecated and will be removed in a future version, the public classes are available in the top-level namespace (:issue:`19711`) +- :func:`pandas.json_normalize` is now exposed in the top-level namespace. + Usage of ``json_normalize`` as ``pandas.io.json.json_normalize`` is now deprecated and + it is recommended to use ``json_normalize`` as :func:`pandas.json_normalize` instead (:issue:`27586`). - .. _whatsnew_1000.prior_deprecations: diff --git a/pandas/__init__.py b/pandas/__init__.py index ec367c62de9db..30b7e5bafe1df 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -175,6 +175,8 @@ read_spss, ) +from pandas.io.json import _json_normalize as json_normalize + from pandas.util._tester import test import pandas.testing import pandas.arrays diff --git a/pandas/io/json/__init__.py b/pandas/io/json/__init__.py index 2382d993df96b..48febb086c302 100644 --- a/pandas/io/json/__init__.py +++ b/pandas/io/json/__init__.py @@ -1,5 +1,5 @@ from pandas.io.json._json import dumps, loads, read_json, to_json -from pandas.io.json._normalize import json_normalize +from pandas.io.json._normalize import _json_normalize, json_normalize from pandas.io.json._table_schema import build_table_schema __all__ = [ @@ -7,6 +7,7 @@ "loads", "read_json", "to_json", + "_json_normalize", "json_normalize", "build_table_schema", ] diff --git a/pandas/io/json/_normalize.py b/pandas/io/json/_normalize.py index df513d4d37d71..3c9c906939e8f 100644 --- a/pandas/io/json/_normalize.py +++ b/pandas/io/json/_normalize.py @@ -8,6 +8,7 @@ import numpy as np from pandas._libs.writers import convert_json_to_lines +from pandas.util._decorators import deprecate from pandas import DataFrame @@ -108,7 +109,7 @@ def nested_to_record( return new_ds -def json_normalize( +def _json_normalize( data: Union[Dict, List[Dict]], record_path: Optional[Union[str, List]] = None, meta: Optional[Union[str, List]] = None, @@ -332,3 +333,8 @@ def _recursive_extract(data, path, seen_meta, level=0): ) result[k] = np.array(v, dtype=object).repeat(lengths) return result + + +json_normalize = deprecate( + "pandas.io.json.json_normalize", _json_normalize, "1.0.0", "pandas.json_normalize" +) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index b832440aca99c..900ba878e4c0a 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -170,6 +170,9 @@ class TestPDApi(Base): "read_spss", ] + # top-level json funcs + funcs_json = ["json_normalize"] + # top-level to_* funcs funcs_to = ["to_datetime", "to_numeric", "to_pickle", "to_timedelta"] @@ -209,6 +212,7 @@ def test_api(self): + self.funcs + self.funcs_option + self.funcs_read + + self.funcs_json + self.funcs_to + self.deprecated_funcs_in_future + self.deprecated_funcs diff --git a/pandas/tests/io/json/test_normalize.py b/pandas/tests/io/json/test_normalize.py index c71c52bce87b8..038dd2df4d632 100644 --- a/pandas/tests/io/json/test_normalize.py +++ b/pandas/tests/io/json/test_normalize.py @@ -3,10 +3,9 @@ import numpy as np import pytest -from pandas import DataFrame, Index +from pandas import DataFrame, Index, json_normalize import pandas.util.testing as tm -from pandas.io.json import json_normalize from pandas.io.json._normalize import nested_to_record @@ -698,3 +697,10 @@ def test_with_large_max_level(self): ] output = nested_to_record(input_data, max_level=max_level) assert output == expected + + def test_deprecated_import(self): + with tm.assert_produces_warning(FutureWarning): + from pandas.io.json import json_normalize + + recs = [{"a": 1, "b": 2, "c": 3}, {"a": 4, "b": 5, "c": 6}] + json_normalize(recs)