Pretty print JSON in Python without backslashes

Viewed 38

If I do:

from bs4 import BeautifulSoup
import json

html_doc = """
<script id="js-context" type="application/json">{"is_completed": false, "is_bookmarked": false, "api_article_bookmark_url": "/api/v1/articles/python-pretty-print/bookmark/", "api_article_completion_status_url": "/api/v1/articles/python-pretty-print/completion_status/"}</script>
"""

soup = BeautifulSoup(html_doc, 'html.parser')

print(soup.find('script').get_text())

I get the JSON from the <script> printed, but it is minified, not expanded (pretty).

{"is_completed": false, "is_bookmarked": false, "api_article_bookmark_url": "/api/v1/articles/python-pretty-print/bookmark/", "api_article_completion_status_url": "/api/v1/articles/lorem-ipsum/"}

So I tried to use:

print(json.dumps(soup.find('script').get_text(), indent=4))

But, then I get a bunch of backslashes in the JSON. I assume that is because I am re-parsing the JSON or something?

"{\"is_completed\": false, \"is_bookmarked\": false, \"api_article_bookmark_url\": \"/api/v1/articles/python-pretty-print/bookmark/\", \"api_article_completion_status_url\": \"/api/v1/articles/lorem-ipsum/\"}"

How can I pretty print the JSON without getting these backslashes?

2 Answers

soup.find('script').get_text() returns a string (which just happens to be serialized JSON). You'll need to parse it into an object with json.loads() & then turn it back into a string to prettify it:

print(json.dumps(json.loads(soup.find('script').get_text()), indent=4))

Result:

{
    "is_completed": false,
    "is_bookmarked": false,
    "api_article_bookmark_url": "/api/v1/articles/python-pretty-print/bookmark/",
    "api_article_completion_status_url": "/api/v1/articles/lorem-ipsum/"
}

Note: this prettifying costs you one deserializing & serializing so I'd advise trying to avoid it.

Try this:

parsed = json.loads(soup.find('script').get_text())
print(json.dumps(parsed, indent=4))
Related