From d1f5292413c88ce1ba8edf45eeafc493481bbd3c Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 10:22:50 +1100 Subject: [PATCH 01/16] Added new parameter escape_forward_slashes to to_json() --- pandas/io/json/_json.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index bfa61253c9c1f..f6f2379af040d 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -114,6 +114,7 @@ def to_json( indent: int = ..., storage_options: StorageOptions = ..., mode: Literal["a", "w"] = ..., + escape_forward_slashes: bool | True = ..., ) -> None: ... @@ -133,9 +134,9 @@ def to_json( indent: int = ..., storage_options: StorageOptions = ..., mode: Literal["a", "w"] = ..., + escape_forward_slashes: bool | True = ..., ) -> str: ... - def to_json( path_or_buf: FilePath | WriteBuffer[str] | WriteBuffer[bytes] | None, obj: NDFrame, @@ -151,6 +152,7 @@ def to_json( indent: int = 0, storage_options: StorageOptions | None = None, mode: Literal["a", "w"] = "w", + escape_forward_slashes: bool | True = ..., ) -> str | None: if orient in ["records", "values"] and index is True: raise ValueError( From aa7a7b07fbfeb0ce54f6de7e981c4d5e95aa9286 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 10:40:41 +1100 Subject: [PATCH 02/16] Wrote removal of backslashes before forward slashes in to_json() where escape_forward_slashes is False --- pandas/io/json/_json.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index f6f2379af040d..f38520a2fd611 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -19,6 +19,8 @@ import numpy as np +import re + from pandas._config import option_context from pandas._libs import lib @@ -220,6 +222,9 @@ def to_json( ) as handles: handles.handle.write(s) else: + if not escape_forward_slashes: + pattern = "\\\\/" + s = re.sub(pattern, "/", "s") return s return None From 675a80bf274b2a7386e1dc835de3360fb8796f0a Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 10:43:36 +1100 Subject: [PATCH 03/16] Added test for when escape_forward_slashes in to_json() is False --- pandas/tests/io/json/test_pandas.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index d67e725233127..bcb136526e1bd 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -2285,6 +2285,23 @@ def test_to_json_ea_null(): """ assert result == expected +def test_to_json_escape_forward_slashes(): + df = DataFrame( + { + "path1": Series(["/escape/three/slashes"], dtype="str"), + "path2": Series(["/"], dtype="str"), + "path3": Series(["ending/"], dtype="str"), + "path4": Series(["/beginning"], dtype="str"), + "path5": Series(["/multiples//multiple"], dtype="str"), + "path6": Series(["//"], dtype="str") + } + ) + result = df.to_json(escape_forward_slashes=False) + expected = """{"path1":"/escape/three/slashes", "path2":"/", + "path3":"ending/", "path4":"/beginning", + "path5":"/multiples//multiple", "path6":"//"}""" + + assert result == expected def test_read_json_lines_rangeindex(): # GH 57429 From 8a1af6407c417608b336b4aee9387ec4298afe40 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 12:50:55 +1100 Subject: [PATCH 04/16] Fixed tests so they correctly respresent the correct output expected --- pandas/tests/io/json/test_pandas.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index bcb136526e1bd..fa55774632070 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -2296,10 +2296,8 @@ def test_to_json_escape_forward_slashes(): "path6": Series(["//"], dtype="str") } ) - result = df.to_json(escape_forward_slashes=False) - expected = """{"path1":"/escape/three/slashes", "path2":"/", - "path3":"ending/", "path4":"/beginning", - "path5":"/multiples//multiple", "path6":"//"}""" + result = df.to_json(orient="records", escape_forward_slashes=False) + expected = """[{"path1":"/escape/three/slashes","path2":"/","path3":"ending/","path4":"/beginning","path5":"/multiples//multiple","path6":"//"}]""" assert result == expected From cbc3186f1138ba3d97f6648ce243ccee1d616327 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 12:53:14 +1100 Subject: [PATCH 05/16] Added correct documentation for changes made to to_json() --- pandas/core/generic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 43078ef3a263c..ed77a6b844b8c 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2342,6 +2342,7 @@ def to_json( indent: int | None = None, storage_options: StorageOptions | None = None, mode: Literal["a", "w"] = "w", + escape_forward_slashes: bool = True, ) -> str | None: """ Convert the object to a JSON string. @@ -2429,6 +2430,9 @@ def to_json( Accepted args are 'w' (writing) and 'a' (append) only. mode='a' is only supported when lines is True and orient is 'records'. + escape_forward_slashes : bool, optional, default True + Remove backward slashes that get added in conversion to json. + Returns ------- None or str From 6de31f8ab67c67bdf7d5d5b9d0d24009700b92ed Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 12:59:51 +1100 Subject: [PATCH 06/16] Fixed issue with value of escape_forward_slashes not being passed into the function --- pandas/core/generic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index ed77a6b844b8c..deaf1a698e0de 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2633,6 +2633,7 @@ def to_json( indent=indent, storage_options=storage_options, mode=mode, + escape_forward_slashes=escape_forward_slashes, ) @final From 4a6a0cfc7bccfa2687e0fb51e731eff73e627837 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 13:05:21 +1100 Subject: [PATCH 07/16] Fixed removal of backward slashes in to_json() --- pandas/io/json/_json.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index f38520a2fd611..e4163b23840e5 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -223,8 +223,22 @@ def to_json( handles.handle.write(s) else: if not escape_forward_slashes: - pattern = "\\\\/" - s = re.sub(pattern, "/", "s") + pattern = r"\/" + i = 1 + new_s = "" + skip = False + for letter in s: + if skip is False: + if letter + s[i] == pattern: + new_s = new_s + r"/" + skip = True + else: + new_s = new_s + letter + else: + skip = False + if i < len(s) - 1: + i = i + 1 + return new_s return s return None From 861495b28e02ceef6d981bb7c261bed1d0c17c43 Mon Sep 17 00:00:00 2001 From: u7955901 Date: Sat, 25 Oct 2025 13:57:14 +1100 Subject: [PATCH 08/16] Remove unused import re --- pandas/io/json/_json.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index e4163b23840e5..b70832cd18e26 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -19,8 +19,6 @@ import numpy as np -import re - from pandas._config import option_context from pandas._libs import lib From 09e16c81e4319da443d1f26e498082daa44b01e5 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sat, 25 Oct 2025 14:16:19 +1100 Subject: [PATCH 09/16] Fixed line too long error --- pandas/tests/io/json/test_pandas.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index fa55774632070..d1a2b27255f5a 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -2285,6 +2285,7 @@ def test_to_json_ea_null(): """ assert result == expected + def test_to_json_escape_forward_slashes(): df = DataFrame( { @@ -2293,14 +2294,19 @@ def test_to_json_escape_forward_slashes(): "path3": Series(["ending/"], dtype="str"), "path4": Series(["/beginning"], dtype="str"), "path5": Series(["/multiples//multiple"], dtype="str"), - "path6": Series(["//"], dtype="str") + "path6": Series(["//"], dtype="str"), } ) result = df.to_json(orient="records", escape_forward_slashes=False) - expected = """[{"path1":"/escape/three/slashes","path2":"/","path3":"ending/","path4":"/beginning","path5":"/multiples//multiple","path6":"//"}]""" + expected1 = """[{"path1":"/escape/three/slashes","path2":"/","path3":"ending/""" "" + expected2 = ( + ""","path4":"/beginning","path5":"/multiples//multiple","path6":"//"}]""" + ) + expected = expected1 + expected2 assert result == expected + def test_read_json_lines_rangeindex(): # GH 57429 data = """ From 3ef9972efd8e876acc5f90e03aa241df2c04a517 Mon Sep 17 00:00:00 2001 From: u7955901 Date: Sat, 25 Oct 2025 14:28:22 +1100 Subject: [PATCH 10/16] Changed formatting of escape forward slashes test data --- pandas/tests/io/json/test_pandas.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index d1a2b27255f5a..a655b771c9dee 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -2298,10 +2298,8 @@ def test_to_json_escape_forward_slashes(): } ) result = df.to_json(orient="records", escape_forward_slashes=False) - expected1 = """[{"path1":"/escape/three/slashes","path2":"/","path3":"ending/""" "" - expected2 = ( - ""","path4":"/beginning","path5":"/multiples//multiple","path6":"//"}]""" - ) + expected1 = '[{"path1":"/escape/three/slashes","path2":"/","path3":"ending/"' + expected2 = ',"path4":"/beginning","path5":"/multiples//multiple","path6":"//"}]' expected = expected1 + expected2 assert result == expected From 436bfc20d6f1567ddb6c6633aaeb69e569c422a1 Mon Sep 17 00:00:00 2001 From: u7955901 Date: Sat, 25 Oct 2025 14:35:18 +1100 Subject: [PATCH 11/16] Update v3.0.0.rst with enhancement description --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 44bc82008e718..8f2c2620786a6 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -228,7 +228,7 @@ Other enhancements - Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`) - Support reading Stata 110-format (Stata 7) dta files (:issue:`47176`) - Switched wheel upload to **PyPI Trusted Publishing** (OIDC) for release-tag pushes in ``wheels.yml``. (:issue:`61718`) -- +- Added functionality to support saving json without escpaing forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) .. --------------------------------------------------------------------------- .. _whatsnew_300.notable_bug_fixes: From 5d2f8a0b0099dcb0792708dc343c84498d7effa1 Mon Sep 17 00:00:00 2001 From: u7955901 Date: Sat, 25 Oct 2025 14:44:05 +1100 Subject: [PATCH 12/16] Update v3.0.0.rst - Fixed spelling mistake --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 8f2c2620786a6..29339cc3d8a24 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -228,7 +228,7 @@ Other enhancements - Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`) - Support reading Stata 110-format (Stata 7) dta files (:issue:`47176`) - Switched wheel upload to **PyPI Trusted Publishing** (OIDC) for release-tag pushes in ``wheels.yml``. (:issue:`61718`) -- Added functionality to support saving json without escpaing forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) +- Added functionality to support saving json without escaping forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) .. --------------------------------------------------------------------------- .. _whatsnew_300.notable_bug_fixes: From 8b676e860d5b5790d264e4e24f9dda466d8dc12a Mon Sep 17 00:00:00 2001 From: u7955901 Date: Sat, 25 Oct 2025 14:48:17 +1100 Subject: [PATCH 13/16] Update v3.0.0.rst - Placed update in alphabetical order --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 29339cc3d8a24..79bb7fe3a1951 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -161,6 +161,7 @@ Other enhancements :func:`pandas.concat`. - :class:`pandas.api.typing.FrozenList` is available for typing the outputs of :attr:`MultiIndex.names`, :attr:`MultiIndex.codes` and :attr:`MultiIndex.levels` (:issue:`58237`) - :class:`pandas.api.typing.SASReader` is available for typing the output of :func:`read_sas` (:issue:`55689`) +- Added functionality to support saving json without escaping forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) - Added :meth:`.Styler.to_typst` to write Styler objects to file, buffer or string in Typst format (:issue:`57617`) - Added missing :meth:`pandas.Series.info` to API reference (:issue:`60926`) - :class:`pandas.api.typing.NoDefault` is available for typing ``no_default`` @@ -228,7 +229,6 @@ Other enhancements - Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`) - Support reading Stata 110-format (Stata 7) dta files (:issue:`47176`) - Switched wheel upload to **PyPI Trusted Publishing** (OIDC) for release-tag pushes in ``wheels.yml``. (:issue:`61718`) -- Added functionality to support saving json without escaping forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) .. --------------------------------------------------------------------------- .. _whatsnew_300.notable_bug_fixes: From dfc457c9f2168114c107a0b8d8a6d7be9d910294 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 25 Oct 2025 03:52:55 +0000 Subject: [PATCH 14/16] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/source/whatsnew/v3.0.0.rst | 2 +- pandas/io/json/_json.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 79bb7fe3a1951..765714282c8fc 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -161,8 +161,8 @@ Other enhancements :func:`pandas.concat`. - :class:`pandas.api.typing.FrozenList` is available for typing the outputs of :attr:`MultiIndex.names`, :attr:`MultiIndex.codes` and :attr:`MultiIndex.levels` (:issue:`58237`) - :class:`pandas.api.typing.SASReader` is available for typing the output of :func:`read_sas` (:issue:`55689`) -- Added functionality to support saving json without escaping forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) - Added :meth:`.Styler.to_typst` to write Styler objects to file, buffer or string in Typst format (:issue:`57617`) +- Added functionality to support saving json without escaping forward slashes by adding to :meth:`DataFrame.to_json` (:issue:`61442`) - Added missing :meth:`pandas.Series.info` to API reference (:issue:`60926`) - :class:`pandas.api.typing.NoDefault` is available for typing ``no_default`` - :func:`DataFrame.to_excel` now raises an ``UserWarning`` when the character count in a cell exceeds Excel's limitation of 32767 characters (:issue:`56954`) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index b70832cd18e26..34123dd40f13b 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -137,6 +137,7 @@ def to_json( escape_forward_slashes: bool | True = ..., ) -> str: ... + def to_json( path_or_buf: FilePath | WriteBuffer[str] | WriteBuffer[bytes] | None, obj: NDFrame, From 3776f2c0e81abcc5960a2ac2f93fbfec561289b9 Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sun, 26 Oct 2025 13:05:25 +1100 Subject: [PATCH 15/16] Fixed issue with incorrect types --- pandas/io/json/_json.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index b70832cd18e26..5109ea99e7d28 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -114,7 +114,7 @@ def to_json( indent: int = ..., storage_options: StorageOptions = ..., mode: Literal["a", "w"] = ..., - escape_forward_slashes: bool | True = ..., + escape_forward_slashes: Literal[True, False] = ..., ) -> None: ... @@ -134,9 +134,10 @@ def to_json( indent: int = ..., storage_options: StorageOptions = ..., mode: Literal["a", "w"] = ..., - escape_forward_slashes: bool | True = ..., + escape_forward_slashes: Literal[True, False] = ..., ) -> str: ... + def to_json( path_or_buf: FilePath | WriteBuffer[str] | WriteBuffer[bytes] | None, obj: NDFrame, @@ -152,7 +153,7 @@ def to_json( indent: int = 0, storage_options: StorageOptions | None = None, mode: Literal["a", "w"] = "w", - escape_forward_slashes: bool | True = ..., + escape_forward_slashes: Literal[True, False] = Literal[True], ) -> str | None: if orient in ["records", "values"] and index is True: raise ValueError( From e92db90f4f4c22d57db64f8174dddb8a282221ac Mon Sep 17 00:00:00 2001 From: Sophie Hewlett Date: Sun, 26 Oct 2025 13:38:01 +1100 Subject: [PATCH 16/16] Removed literal type from default --- pandas/io/json/_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index 5109ea99e7d28..62d3b60f7c0f2 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -153,7 +153,7 @@ def to_json( indent: int = 0, storage_options: StorageOptions | None = None, mode: Literal["a", "w"] = "w", - escape_forward_slashes: Literal[True, False] = Literal[True], + escape_forward_slashes: Literal[True, False] = True, ) -> str | None: if orient in ["records", "values"] and index is True: raise ValueError(