Pretty printing JSON and XML in the shell

Last year I read Craig Hockenberry’s magnus opus – a huge collection of information about the OS X Terminal and the Bash shell. It’s worth reading in its entirety, even if you don’t use a Mac. My favourite tips were opt-clicking to jump around in Terminal (which makes Vim far more usable for me), and using the lsof command when a disk won’t eject. Both super useful.

At the same time, I read Dr. Drang’s suggestion that we write up our own tips. I wrote this post at the time, and then it sat in drafts for over a year. Oops. Anyway, here are a few tips from me.

I work a lot with website APIs, which typically return responses that are formatted in XML or JSON. To save bandwidth, these responses are minified (stripped of unnecessary whitespace and newlines). That’s fine for a program, but it’s quite painful if I’m reading it.

Luckily, OS X includes a few tools for pretty printing JSON and XML. This makes the responses substantially easier to read for a human.

<!– ```console $ curl “http://xkcd.com/rss.xml” xkcd.comhttp://xkcd.com/xkcd.com: A webcomic of romance and math humor.enRed Car … $ curl “http://xkcd.com/rss.xml” | xmllint –format - xkcd.com http://xkcd.com/ xkcd.com: A webcomic of romance and math humor. en Red Car … “` –>
  • To tidy up XML, pipe the output to xmlint --format -:

    $curl "http://xkcd.com/rss.xml"
    <?xml version="1.0" encoding="utf-8"?>
    <rss version="2.0"><channel><title>xkcd.com</title><link>http://xkcd.com/</lnk><description>xkcd.com: A webcomic of romance and math humor.</lnk></description><language>en</language><item><title>Red Car</title> ...
    
    $curl "http://xkcd.com/rss.xml" | xmllint --format -
    <?xml version="1.0" encoding="utf-8"?>
    <rss version="2.0">
      <channel>
        <title>xkcd.com</title>
        <link>http://xkcd.com/</link>
        <description>xkcd.com: A webcomic of romance and math humor.</description>
        <language>en</language>
        <item>
          <title>Red Car</title>
    ...

    This is just the tip of what xmllint can do – and it turns out Apple has been quietly including it since at least Mavericks. It’s available in the package manager of most Linux distros.

    I don’t use the advanced features much – once I want to start unpicking the XML, I break out Python and the xml.etree module – but it’s useful for quick debugging and raw responses.