# Should json restrict string indentation to JSON whitespace?

**URL:** <https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060>\
**Category:** Ideas\
**Created:** [September 15, 2026, 6:27am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060 "2026-09-15T06:27:58Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlsneto](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jlsneto/32/37474_2.png) [@jlsneto](https://discuss.python.org/u/jlsneto)\
**Post date:** [September 15, 2026, 6:27am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/1 "2026-09-15T06:27:58Z")

</div>

The `json` module accepts arbitrary strings for `indent`. Depending on the string and input data, this can produce invalid JSON or valid JSON with different values.

For example:

```python
import json

data = [1, 2]

for indent in ["4", "1", "-", "1e", "1."]:
    text = json.dumps(data, indent=indent)
    print(repr(indent), json.loads(text))

```

```plaintext
'4' [41, 42]
'1' [11, 12]
'-' [-1, -2]
'1e' [10.0, 100.0]
'1.' [1.1, 1.2]

```

For a typical object such as `{"name": "example", "values": [1, 2]}`, those same strings produce invalid JSON instead. This was reproduced on CPython 3.14.5 on Windows, including the Python encoder fallback.

### Reproducible test

The test compares against serialization without indentation, excluding normal JSON conversions from the comparison.

```python
import json

documents = {
    "object": {
        "name": "example",
        "active": True,
        "values": [1, 2],
        "metadata": None,
    },
    "numeric_array": [1, 2],
}

indents = [
    None, 4, 0, -1, "", " ", "\t", "\n", "\r",
    " \t\n\r", "4", "0", "1", " 4", "-", "-1",
    "1e", "1.", "0.", "banana", "true", "null",
    "\f", "\v", "\u00a0", "\u2003",
]

for name, data in documents.items():
    baseline = json.loads(json.dumps(data))

    for indent in indents:
        text = json.dumps(data, indent=indent)

        try:
            decoded = json.loads(text)
        except json.JSONDecodeError:
            status = "invalid JSON"
        else:
            status = (
                "unchanged"
                if decoded == baseline
                else f"changed to {decoded!r}"
            )

        print(f"{name}: indent={indent!r}: {status}")

```

### Proposal and compatibility

[bpo-41998 / GH-86164](https://github.com/python/cpython/issues/86164) previously reported field injection through `indent` and proposed converting it to an integer. It was closed as “not a bug,” with validation considered the application’s responsibility.

Would a narrower change be worth considering: retain string indentation, but reject characters outside JSON’s whitespace set—space, tab, LF and CR—as defined in [RFC 8259](https://www.rfc-editor.org/rfc/rfc8259#section-2)?

Empty strings, combinations of those four characters, integers and `None` would remain supported. `str.isspace()` would be too permissive because it accepts additional characters outside JSON’s whitespace set.

I recognize this would narrow documented behavior. Are there use cases for non-whitespace indentation that make this restriction undesirable, or would preventing these effects justify a compatibility transition?

---

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [September 15, 2026, 7:14am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/2 "2026-09-15T07:14:45Z")

</div>

I do fully agree that validation is application’s responsibility, but IMO that does not imply that adding another line of defence is not a good idea.

According to the docs, the purpose of the _indent_ argument is pretty-printing. There is no valid use-case for indenting with a non-whitespace string . It produces invalid output (1) or modified output, so it is at least an error. The linked issue was closed in 2020 as “not a bug”. That’s correct, but it would be nice if a patch would be accepted as an enahncement. In 2026 AI tools are searching for anything that could be misused like crazy.

\_\_\_\_  
Added note 1: later in the discussion it was argued that human readable “pretty” output does not need to be valid JSON. That’s a fair point.

---

<div class="post-metadata">

**Author:** ![petercordia](https://avatars.discourse-cdn.com/v4/letter/p/bb73d2/32.png) [@petercordia](https://discuss.python.org/u/petercordia)\
**Post date:** [September 15, 2026, 7:34am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/3 "2026-09-15T07:34:42Z")

</div>

I think we should not prevent this. The user is a responsive adult. If the user wants to use ` *****` for the indent, and explicitly provides `indent="*****"` that’s what the user explicitly asked for. It can be very frustrating when you want something unusual and the library maintainers decided to put in an `assert` that blocks you from doing what you want.

---

<div class="post-metadata">

**Author:** ![petersuter](https://avatars.discourse-cdn.com/v4/letter/p/13edae/32.png) [@petersuter](https://discuss.python.org/u/petersuter)\
**Post date:** [September 15, 2026, 7:51am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/4 "2026-09-15T07:51:19Z")

</div>

> Are there use cases for non-whitespace indentation

[Github search](https://github.com/search?q=json.dumps+indent%3D%22%7C+language%3APython&type=code) finds some cases like `json.dumps(body, indent="| ")`.

---

<div class="post-metadata">

**Author:** ![hooram95](https://avatars.discourse-cdn.com/v4/letter/h/58f4c7/32.png) [@hooram95](https://discuss.python.org/u/hooram95)\
**Post date:** [September 15, 2026, 8:32am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/5 "2026-09-15T08:32:39Z")

</div>

I think restricting string indentation to JSON whitespace makes sense. Allowing arbitrary characters can unexpectedly change the parsed values, so rejecting non-whitespace characters would make `indent` much safer and more predictable without affecting normal formatting use cases.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [September 15, 2026, 8:34am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/6 "2026-09-15T08:34:51Z")

</div>

The `indent` is almost always a string literal. It’s not like this is an externally-controlled attack or anything. Yes, you can use this to create something that isn’t valid JSON… congrats. There are already plenty of other ways to do that (in fact, `allow_nan=True` _is the default_, and is actually in violation of the spec); this is a pretty benign one.

---

<div class="post-metadata">

**Author:** ![jlsneto](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jlsneto/32/37474_2.png) [@jlsneto](https://discuss.python.org/u/jlsneto)\
**Post date:** [September 15, 2026, 8:53am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/7 "2026-09-15T08:53:02Z")

</div>

I checked the Lambda example. It uses `indent="| "` for printing, while the SQS message and HTTP response use regular JSON output. I can see why restricting it would break a useful formatting choice.

What surprised me was that other indent strings can produce valid JSON with different numeric values. Would a short note in the docs about that behavior be worth adding?

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 15, 2026, 9:38am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/8 "2026-09-15T09:38:54Z")

</div>

Garbage In – Garbage Out.

It is not that passing non-whitespace indent is a common error. The `indent` argument is usually hardcoded. If it is dynamic – it is more convenient to use an integer. `indent` is used to produce more human readable output, and we see that there are use cases to produce human readable representation even if it is not JSON.

BTW, there is also the `separators` parameter. Normally, it only takes `(', ', ': ')`, `(',', ': ')`, or `(',', ':')`, but there is no check, and you can use arbitrary values and produce weird looking or invalid JSON. This is up to you.

---

<div class="post-metadata">

**Author:** ![Paddy3118](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/paddy3118/32/1396_2.png) [@Paddy3118](https://discuss.python.org/u/Paddy3118)\
**Post date:** [September 15, 2026, 9:39am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/9 "2026-09-15T09:39:57Z")

</div>

If all examples use typical values that cause no problems, and it is already called indent, which to me implies whitespace. I think there should be a limit to protectionism, and that reading docs and trying things out are a part of learning the _ **extent** _ of a library.

> “Doctor doctor, it hurts if I do this”  
> _“Then don’t do it, then!”_  
> 😉

---

<div class="post-metadata">

**Author:** ![srittau](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/srittau/32/237_2.png) [@srittau](https://discuss.python.org/u/srittau)\
**Post date:** [September 16, 2026, 8:09am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/10 "2026-09-16T08:09:34Z")

</div>

I’ve opened [[json] Require a `LiteralString` for `indent` argument by srittau · Pull Request #16402 · python/typeshed · GitHub](https://github.com/python/typeshed/pull/16402) against typeshed. This should at least prevent users using type checkers from using non-literal strings for `indent` without an explicit “I know what I’m doing” cast.

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 16, 2026, 9:58am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/11 "2026-09-16T09:58:52Z")

</div>

How would you write a wrapper around `json.dumps()`?

How would you write something like `indent='\t' if indent >= 8 else indent`?

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [September 16, 2026, 10:01am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/12 "2026-09-16T10:01:12Z")

</div>

> [@srittau](#):
>
> This should at least prevent users…

Why restrict people? What’s the point? Is there an actual threat being protected against?

---

<div class="post-metadata">

**Author:** ![srittau](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/srittau/32/237_2.png) [@srittau](https://discuss.python.org/u/srittau)\
**Post date:** [September 16, 2026, 10:27am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/13 "2026-09-16T10:27:29Z")

</div>

> Why restrict people? What’s the point? Is there an actual threat being protected against?

The threat was described in the original post. This is not a restriction as it can easily be worked around using a `cast`. Should we remove `LiteralString` from SQL queries as well?

---

<div class="post-metadata">

**Author:** ![srittau](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/srittau/32/237_2.png) [@srittau](https://discuss.python.org/u/srittau)\
**Post date:** [September 16, 2026, 10:29am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/14 "2026-09-16T10:29:22Z")

</div>

> How would you write a wrapper around `json.dumps()`?
> 
> How would you write something like `indent='\t' if indent >= 8 else indent`?

Was this directed at me? In that case I don’t understand the question or the problem.

_Edit_: Could you give a full example that you think is problematic? `indent='\t' if indent >= 8 else indent` isn’t, depending on how exactly `indent` is typed.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [September 16, 2026, 10:30am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/15 "2026-09-16T10:30:27Z")

</div>

> [@srittau](#):
>
> Should we remove `LiteralString` from SQL queries as well?

SQL injection is a very real and well-known threat. What is the threat posed by non-literal indentation in JSON encoding?

You can’t just point a finger and scream “EMERGENCY” to demand changes. I know that’s how certain politicians work, but we strive to have better standards in technical discussions.

---

<div class="post-metadata">

**Author:** ![srittau](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/srittau/32/237_2.png) [@srittau](https://discuss.python.org/u/srittau)\
**Post date:** [September 16, 2026, 10:35am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/16 "2026-09-16T10:35:40Z")

</div>

> [@Rosuav](#):
>
> You can’t just point a finger and scream “EMERGENCY” to demand changes. I know that’s how certain politicians work, but we strive to have better standards in technical discussions.

Sorry, but this personal attack disqualifies you from any further replies on my part to you in this thread.

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 16, 2026, 10:40am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/17 "2026-09-16T10:40:51Z")

</div>

“If you don’t give people a long enough rope to hang themselves, they’ll use a garden hose.”

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [September 16, 2026, 10:46am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/18 "2026-09-16T10:46:07Z")

</div>

> [@srittau](#):
>
> Sorry, but this personal attack disqualifies you from any further replies on my part to you in this thread.

Fair enough, but the question is valid and still stands. What specific threat does this capability enable? Remember that `indent` is intended for pretty-printing (it says so in the documentation), so problems with code that reads the output from `dump(..., indent=something)` are to an extent caused by incorrect use of the argument.

---

<div class="post-metadata">

**Author:** ![srittau](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/srittau/32/237_2.png) [@srittau](https://discuss.python.org/u/srittau)\
**Post date:** [September 16, 2026, 10:56am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/19 "2026-09-16T10:56:04Z")

</div>

> [@pf\_moore](#):
>
> What specific threat does this capability enable? Remember that `indent` is intended for pretty-printing (it says so in the documentation), so problems with code that reads the output from `dump(..., indent=something)` are to an extent caused by incorrect use of the argument.

Exactly, `LiteralString` flags potentially incorrect use, for example by passing unverified user input to it. On the other hand it should be low impact, because (as was pointed out in this thread), it is usually a string literal anyway. (And mypy primer seems to agree.) And in the few cases where it isn’t (for example, because the indention string – not level – is read from a config file), a simple cast to flag this is easy enough.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [September 16, 2026, 11:03am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/20 "2026-09-16T11:03:28Z")

</div>

> [@srittau](#):
>
> Sorry, but this personal attack disqualifies you from any further replies on my part to you in this thread

That’s fine. It’s not my responsibility to prove that your change should be rejected, it’s your responsibility to prove that it should be accepted. Maybe you don’t like the way I made my point, but the point itself still stands, and you declined to answer it.

[Next page](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060.md?page=2)
