Skip to content

Commit 2b1fdea

Browse files
dshemetovim-vinicius
authored and
im-vinicius
committed
API/BUG: Make to_json index= arg consistent with orient arg (pandas-dev#52143)
* API/BUG: Make to_json index= consistent with orient - split and table allow index=True/False - records and values only allow index=False - index and columns only allow index=True - raise for contradictions in the latter two - see pandas-dev#25513 * style: lint * style: make mypy happy * review: simplify * review: clarify and consolidate branches * style: add explainer comment * doc: change error message in _json * docs: update whatsnew 2.1.0 * docs: sort whatsnew
1 parent 5006ddf commit 2b1fdea

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

doc/source/whatsnew/v2.1.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ Other enhancements
9292
- Implemented ``__pandas_priority__`` to allow custom types to take precedence over :class:`DataFrame`, :class:`Series`, :class:`Index`, or :class:`ExtensionArray` for arithmetic operations, :ref:`see the developer guide <extending.pandas_priority>` (:issue:`48347`)
9393
- Improve error message when having incompatible columns using :meth:`DataFrame.merge` (:issue:`51861`)
9494
- Improve error message when setting :class:`DataFrame` with wrong number of columns through :meth:`DataFrame.isetitem` (:issue:`51701`)
95+
- Improved error handling when using :meth:`DataFrame.to_json` with incompatible ``index`` and ``orient`` arguments (:issue:`52143`)
9596
- Improved error message when creating a DataFrame with empty data (0 rows), no index and an incorrect number of columns. (:issue:`52084`)
9697
- Let :meth:`DataFrame.to_feather` accept a non-default :class:`Index` and non-string column names (:issue:`51787`)
9798
- Performance improvement in :func:`read_csv` (:issue:`52632`) with ``engine="c"``
9899
- :meth:`Categorical.from_codes` has gotten a ``validate`` parameter (:issue:`50975`)
99100
- Performance improvement in :func:`concat` with homogeneous ``np.float64`` or ``np.float32`` dtypes (:issue:`52685`)
100101
- Performance improvement in :meth:`DataFrame.filter` when ``items`` is given (:issue:`52941`)
101-
-
102102

103103
.. ---------------------------------------------------------------------------
104104
.. _whatsnew_210.notable_bug_fixes:

pandas/core/generic.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -2306,7 +2306,7 @@ def to_json(
23062306
default_handler: Callable[[Any], JSONSerializable] | None = None,
23072307
lines: bool_t = False,
23082308
compression: CompressionOptions = "infer",
2309-
index: bool_t = True,
2309+
index: bool_t | None = None,
23102310
indent: int | None = None,
23112311
storage_options: StorageOptions = None,
23122312
mode: Literal["a", "w"] = "w",
@@ -2375,10 +2375,11 @@ def to_json(
23752375
23762376
.. versionchanged:: 1.4.0 Zstandard support.
23772377
2378-
index : bool, default True
2379-
Whether to include the index values in the JSON string. Not
2380-
including the index (``index=False``) is only supported when
2381-
orient is 'split' or 'table'.
2378+
index : bool or None, default None
2379+
The index is only used when 'orient' is 'split', 'index', 'column',
2380+
or 'table'. Of these, 'index' and 'column' do not support
2381+
`index=False`.
2382+
23822383
indent : int, optional
23832384
Length of whitespace used to indent each record.
23842385

pandas/io/json/_json.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def to_json(
100100
default_handler: Callable[[Any], JSONSerializable] | None = ...,
101101
lines: bool = ...,
102102
compression: CompressionOptions = ...,
103-
index: bool = ...,
103+
index: bool | None = ...,
104104
indent: int = ...,
105105
storage_options: StorageOptions = ...,
106106
mode: Literal["a", "w"] = ...,
@@ -120,7 +120,7 @@ def to_json(
120120
default_handler: Callable[[Any], JSONSerializable] | None = ...,
121121
lines: bool = ...,
122122
compression: CompressionOptions = ...,
123-
index: bool = ...,
123+
index: bool | None = ...,
124124
indent: int = ...,
125125
storage_options: StorageOptions = ...,
126126
mode: Literal["a", "w"] = ...,
@@ -139,15 +139,24 @@ def to_json(
139139
default_handler: Callable[[Any], JSONSerializable] | None = None,
140140
lines: bool = False,
141141
compression: CompressionOptions = "infer",
142-
index: bool = True,
142+
index: bool | None = None,
143143
indent: int = 0,
144144
storage_options: StorageOptions = None,
145145
mode: Literal["a", "w"] = "w",
146146
) -> str | None:
147-
if not index and orient not in ["split", "table"]:
147+
if orient in ["records", "values"] and index is True:
148148
raise ValueError(
149-
"'index=False' is only valid when 'orient' is 'split' or 'table'"
149+
"'index=True' is only valid when 'orient' is 'split', 'table', "
150+
"'index', or 'columns'."
150151
)
152+
elif orient in ["index", "columns"] and index is False:
153+
raise ValueError(
154+
"'index=False' is only valid when 'orient' is 'split', 'table', "
155+
"'records', or 'values'."
156+
)
157+
elif index is None:
158+
# will be ignored for orient='records' and 'values'
159+
index = True
151160

152161
if lines and orient != "records":
153162
raise ValueError("'lines' keyword only valid when 'orient' is records")

pandas/tests/io/json/test_pandas.py

+20-3
Original file line numberDiff line numberDiff line change
@@ -1472,17 +1472,34 @@ def test_index_false_to_json_table(self, data):
14721472

14731473
assert result == expected
14741474

1475-
@pytest.mark.parametrize("orient", ["records", "index", "columns", "values"])
1475+
@pytest.mark.parametrize("orient", ["index", "columns"])
14761476
def test_index_false_error_to_json(self, orient):
1477-
# GH 17394
1477+
# GH 17394, 25513
14781478
# Testing error message from to_json with index=False
14791479

14801480
df = DataFrame([[1, 2], [4, 5]], columns=["a", "b"])
14811481

1482-
msg = "'index=False' is only valid when 'orient' is 'split' or 'table'"
1482+
msg = (
1483+
"'index=False' is only valid when 'orient' is 'split', "
1484+
"'table', 'records', or 'values'"
1485+
)
14831486
with pytest.raises(ValueError, match=msg):
14841487
df.to_json(orient=orient, index=False)
14851488

1489+
@pytest.mark.parametrize("orient", ["records", "values"])
1490+
def test_index_true_error_to_json(self, orient):
1491+
# GH 25513
1492+
# Testing error message from to_json with index=True
1493+
1494+
df = DataFrame([[1, 2], [4, 5]], columns=["a", "b"])
1495+
1496+
msg = (
1497+
"'index=True' is only valid when 'orient' is 'split', "
1498+
"'table', 'index', or 'columns'"
1499+
)
1500+
with pytest.raises(ValueError, match=msg):
1501+
df.to_json(orient=orient, index=True)
1502+
14861503
@pytest.mark.parametrize("orient", ["split", "table"])
14871504
@pytest.mark.parametrize("index", [True, False])
14881505
def test_index_false_from_json_to_json(self, orient, index):

0 commit comments

Comments
 (0)