# 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:** 2

<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, 11:05am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/21 "2026-09-16T11:05:22Z")

</div>

> [@srittau](#):
>
> Exactly, `LiteralString` flags potentially incorrect use

But you still haven’t answered the question. **Why** is a non-literal argument “potentially incorrect”? After all, `indent="8"` is just as (potentially) incorrect, but won’t get flagged.

And as @storchaka noted, valid use cases like a `json.dumps` wrapper which passes user-supplied arguments (including `indent`) on from the caller to `dumps` will be flagged as (potentially) incorrect, when they clearly aren’t.

Maybe it won’t cause much harm because most uses won’t be affected. But that’s not the question - the question is what actual _benefit_ will it provide? Not just handwavy “might be incorrect” claims, do you (or the OP) have real examples of code that has failed because a non-literal has been passed to `indent`?

---

<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, 11:13am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/22 "2026-09-16T11:13:25Z")

</div>

> [@pf\_moore](#):
>
> **Why** is a non-literal argument “potentially incorrect”?

It’s potentially dangerous, not necessarily incorrect. Same as with SQL injection. `LiteralString` is an easy way to f;ag that

> [@pf\_moore](#):
>
> After all, `indent="8"` is just as (potentially) incorrect, but won’t get flagged.

The type system doesn’t support flagging all potentially incorrect cases, neither here nor elsewhere.

> [@pf\_moore](#):
>
> And as @storchaka noted, valid use cases like a `json.dumps` wrapper which passes user-supplied arguments (including `indent`) on from the caller to `dumps` will be flagged as (potentially) incorrect, when they clearly aren’t.

This is just incorrect, wrappers are still easily possible.

---

<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, 11:19am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/23 "2026-09-16T11:19:11Z")

</div>

> [@srittau](#):
>
> Same as with SQL injection.

And SQL injection has real, documented cases of harm being caused as a result. That’s what I’m asking for here, and I’m hearing nothing.

> [@srittau](#):
>
> This is just incorrect, wrappers are still easily possible.

I didn’t say they weren’t possible, just that they would be flagged. And “of course” it’s possible to suppress the warning. But suppression is a cost (code needs to change), so all I’m asking is what’s the benefit to offset the cost?

You seem to be convinced that “potentially dangerous” with no explicit examples of the danger is enough justification. I disagree. I doubt either of us will persuade the other. So I think we should drop the discussion. I’m personally pretty sure that your proposal won’t get adopted as it stands, but if it does, then so be it, you were right and I was wrong. It’s not like I can’t make mistakes 🙂

---

<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, 11:20am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/24 "2026-09-16T11:20:56Z")

</div>

> [@pf\_moore](#):
>
> I didn’t say they weren’t possible, just that they would be flagged.

I get the feeling that people don’t understand how `LiteralString` works. Nothing gets flagged in the following example:

```python
def wrap_dumps(..., indent: LiteralString | int | None) -> str:
    return json.dumps(..., indent="\t" if indent == 8 else indent)

```

---

<div class="post-metadata">

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

</div>

Isn’t this kind of things better served by `flake8-bandit` and the `ruff` equivalent ? It’s better to rely on these tools than introduce false positive warnings in Python.

---

<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, 11:32am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/26 "2026-09-16T11:32:46Z")

</div>

> [@srittau](#):
>
> I get the feeling that people don’t understand how `LiteralString` works. Nothing gets flagged in the following example:
> 
> ```python
> def wrap_dumps(..., indent: LiteralString | int | None) -> str:
> return json.dumps(..., indent="\t" if indent == 8 else indent)
> 
> ```

But if the code is currently

```python
def wrap_dumps(..., indent: str | int | None) -> str:
    return json.dumps(..., indent="\t" if indent == 8 else indent)

```

then the definition of `wrap_dumps` needs to change to avoid errors\[1\].

As I say, you’re not going to convince me, and I’m not going to convince you. Let’s drop this.

* * *

1. And just to make things worse, the behaviour appears to differ between type checkers - in my tests, mypy doesn’t seem to flag passing a str to a parameter annotated as `LiteralString`

---

<div class="post-metadata">

**Author:** ![duncathan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/duncathan/32/25521_2.png) [@duncathan](https://discuss.python.org/u/duncathan)\
**Post date:** [September 16, 2026, 1:52pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/27 "2026-09-16T13:52:12Z")

</div>

I think it comes off more rudely than you likely intended for your PR description to talk about how the negative feedback is from people not understanding how `LiteralString` works. While there is certainly misunderstanding here, I’m not sure it’s productive to just dismiss all concerns where there’s any misunderstanding.

---

<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 16, 2026, 2:33pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/28 "2026-09-16T14:33:56Z")

</div>

The opinions do not converge. Could we just add one sentence to the docs? A small warning that improper argument values compromise the validity of `JSONEncoder` output. Most of you find it fully obvious, but it isn’t. In many other cases improper arguments trigger exceptions.

---

<div class="post-metadata">

**Author:** ![Liz](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/liz/32/15021_2.png) [@Liz](https://discuss.python.org/u/Liz)\
**Post date:** [September 16, 2026, 2:55pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/29 "2026-09-16T14:55:32Z")

</div>

I would prefer if tools in the standard library didnt produce garbage output and rejected garbage input. There are a lot of cases where people have written things off as “garbage in, garbage out” that later turn out to be abusable in some way.

a json encoder shouldn’t need to care about breaking people using it for things other than encoding json.

---

<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, 6:03pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/30 "2026-09-16T18:03:13Z")

</div>

> [@Liz](#):
>
> I would prefer if tools in the standard library didnt produce garbage output and rejected garbage input.

I don’t think that’s the whole story here, though. People have demonstrated real use cases for things like `indent="| "`. Working out precisely what constitutes “garbage input” is far harder than banning everything but whitespace.

> [@Liz](#):
>
> a json encoder shouldn’t need to care about breaking people using it for things other than encoding json

Agreed, but the `indent` parameter isn’t about encoding. It’s explicitly documented as being for _pretty printing_. And pretty-printed JSON doesn’t need to be valid JSON.

Maybe it would have been better to have a distinct, dedicated pretty-printing function. But that’s not the situation we’re in now, and we can’t simply retroactively redefine the purpose of the indent parameter.

---

<div class="post-metadata">

**Author:** ![vstinner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vstinner/32/15130_2.png) [@vstinner](https://discuss.python.org/u/vstinner)\
**Post date:** [September 16, 2026, 6:13pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/31 "2026-09-16T18:13:44Z")

</div>

For what is worth, the command line interface only accepts integers (reject strings):

```python
$ echo '[1, 2, 3]' | python -m json --indent ' '
usage: python -m json [-h] [--sort-keys] [--no-ensure-ascii] [--json-lines] [--indent INDENT | --tab | --no-indent | --compact]
                      [infile] [outfile]
python -m json: error: argument --indent: invalid int value: ' '

$ echo '[1, 2, 3]' | python -m json --indent 4
[
    1,
    2,
    3
]

```

---

<div class="post-metadata">

**Author:** ![Liz](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/liz/32/15021_2.png) [@Liz](https://discuss.python.org/u/Liz)\
**Post date:** [September 16, 2026, 6:50pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/32 "2026-09-16T18:50:40Z")

</div>

> [@pf\_moore](#):
>
> > [@Liz](#):
> >
> > a json encoder shouldn’t need to care about breaking people using it for things other than encoding json
> 
> Agreed, but the `indent` parameter isn’t about encoding. It’s explicitly documented as being for _pretty printing_. And pretty-printed JSON doesn’t need to be valid JSON.

The example that says “pretty print” uses a number, and demonstrates it in contrast to the most compact representation, and the documentation only provides examples that produce valid json.

I can’t read the choice of words “pretty print” to mean “we intended to support an encoder creating invalid representations”, it seems obvious that the intent is about layout, not creating non-json outputs.

---

<div class="post-metadata">

**Author:** ![mikeshardmind](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mikeshardmind/32/14381_2.png) [@mikeshardmind](https://discuss.python.org/u/mikeshardmind)\
**Post date:** [September 16, 2026, 6:59pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/33 "2026-09-16T18:59:38Z")

</div>

The functions that take an indent parameter, as well as the encoder class’s methods use language that indicates the result is intended to be valid json, while there is a section on caveats to that, it does not include this use of indent, and only covers things like `inf` and invalid unicode sequences.

json.dump:

> Serialize _obj_ as a JSON formatted stream to _fp_ (a `.write()`-supporting [file-like object](https://docs.python.org/3/glossary.html#term-file-like-object)) using this [Python-to-JSON conversion table](https://docs.python.org/3/library/json.html#py-to-json-table).

json.dumps:

> Serialize _obj_ to a JSON formatted [`str`](https://docs.python.org/3/builtins/stdtypes.html#str "str") using this [conversion table](https://docs.python.org/3/library/json.html#py-to-json-table). The arguments have the same meaning as in [`dump()`](https://docs.python.org/3/library/json.html#json.dump "json.dump").

json.JSONEncoder.encode

> Return a JSON string representation of a Python data structure, _o_. For example:

---

<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, 6:59pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/34 "2026-09-16T18:59:42Z")

</div>

> [@Liz](#):
>
> I can’t read the choice of words “pretty print” to mean “we intended to support an encoder creating invalid representations”, it seems obvious that the intent is about layout, not creating non-json outputs.

Don’t forget, the **default settings** are technically invalid (allowing infinity and nan). The JSON module, like the rest of Python, values practicality over purity.

---

<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 17, 2026, 12:46am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/35 "2026-09-17T00:46:38Z")

</div>

I ran into this in production years ago. The mistake was mine: I passed a variable as `indent` without checking it properly. I don’t remember the exact value or have the original code anymore, but I remember spending time tracking down inconsistencies because the output still parsed successfully.

I didn’t bring it up at the time. A similar issue came up recently, which prompted me to investigate this behavior more carefully and open this discussion. I can’t say how common this is for others, but I’ve encountered it more than once in my own work.

I thought `indent` only controlled how the output was formatted. When I noticed the values were different, I didn’t initially suspect that argument.

---

<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 17, 2026, 1:00am UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/36 "2026-09-17T01:00:04Z")

</div>

Your CLI example made me wonder whether an opt-in strict mode could be useful in `json.dumps()` as well.

Rather than changing the default, could something like `strict=True` reject indentation containing characters other than JSON whitespace? That would preserve the existing formatting uses while letting applications catch these mistakes before saving or sending the output.

Unlike checking whether the output parses, this would also catch the cases where indentation changes numeric values but leaves the JSON valid.

The name and scope would need discussion, especially given the points raised about `allow_nan` and `separators`. Would this be worth exploring, or is the extra API complexity hard to justify compared with application-side validation?

---

<div class="post-metadata">

**Author:** ![vstinner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vstinner/32/15130_2.png) [@vstinner](https://discuss.python.org/u/vstinner)\
**Post date:** [September 17, 2026, 2:53pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/37 "2026-09-17T14:53:52Z")

</div>

IMO json should not be modified. If something should change, I would recommend modifying the documentation to _mention_ that passing a string with characters other than spaces to _indent_ produces invalid JSON. I suppose that “spaces” here is limited to tabs (`'\t'`) and ASCII space (`' '`), and that other “Unicode” space characters (such as `'\u1680'`) also produce invalid JSON.

---

<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 18, 2026, 1:57pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/38 "2026-09-18T13:57:56Z")

</div>

Modifying the quote from @vstinner above:

> I would recommend modifying the documentation to _mention_ that passing a string with characters other than spaces `and tabs` to _indent_ runs the risk of producing invalid JSON `or even parsable JSON with incorrect values`.

Assuming that spaces, tabs, and any mixture of tabs and spaces, are guaranteed to work.

---

<div class="post-metadata">

**Author:** ![bwoodsend](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bwoodsend/32/4027_2.png) [@bwoodsend](https://discuss.python.org/u/bwoodsend)\
**Post date:** [September 18, 2026, 7:55pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/39 "2026-09-18T19:55:52Z")

</div>

Newlines (both `\n` and `\r`) are allowed too.

---

<div class="post-metadata">

**Author:** ![matthewyu0311](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/matthewyu0311/32/20118_2.png) [@matthewyu0311](https://discuss.python.org/u/matthewyu0311)\
**Post date:** [September 19, 2026, 1:16pm UTC](https://discuss.python.org/t/should-json-restrict-string-indentation-to-json-whitespace/109060/40 "2026-09-19T13:16:22Z")

</div>

I don’t think this is actually necessary in most cases, but given the many types of things we accept for indent: non-empty `str`, positive integers, 0/negative integers/`""`, `None`, it isn’t hard to conceive how users might find it confusing.

Perhaps we can add a `json.sanitize_indent(indent)`utility function that returns the original value or raises `ValueError` if the indent would result in either invalid JSON or injections?

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