<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mike Fiedler</title>
    <description>The latest articles on DEV Community by Mike Fiedler (@miketheman).</description>
    <link>https://dev.to/miketheman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F175445%2Fd1b91405-889a-4a82-9010-43aac2c30314.jpeg</url>
      <title>DEV Community: Mike Fiedler</title>
      <link>https://dev.to/miketheman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miketheman"/>
    <language>en</language>
    <item>
      <title>Visual Audit Homebrew Programs</title>
      <dc:creator>Mike Fiedler</dc:creator>
      <pubDate>Sun, 10 May 2020 15:04:42 +0000</pubDate>
      <link>https://dev.to/miketheman/visual-audit-homebrew-programs-gjg</link>
      <guid>https://dev.to/miketheman/visual-audit-homebrew-programs-gjg</guid>
      <description>&lt;p&gt;I use a Mac computer as my primary development machine. My personal one is where I spend a lot of time experimenting, self-learning, trying things out.&lt;br&gt;
One awesome way to install software on macOS is to use &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;, which boils down the process of downloading, compiling, installing software (and any associated dependencies) to a simpler process, often with a single command, e.g. &lt;code&gt;brew install httpie&lt;/code&gt; to get the &lt;a href="https://httpie.org/"&gt;HTTPie&lt;/a&gt; command line client.&lt;/p&gt;

&lt;p&gt;However, since it's so easy to install a variety of packages and programs, oftentimes I'll have installed a program to try something out, and never need it again. The total count of packages installed via Homebrew can be seen like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew list | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
325
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I definitely don't recall installing all of these - and over time that becomes a heavier burden to carry. Each package can use up some disk space, but more importantly, every time a &lt;code&gt;brew upgrade&lt;/code&gt; is run, it may install new versions of software you don't use, so that takes up more time - which is even more valuable than disk space. If you're running out of disk space, read: &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/clpsplug" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T52xIQhV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--AM-LtNzn--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/43590/9796aed2-75e3-499d-b898-319d3c633737.jpeg" alt="clpsplug image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/clpsplug/seriously-periodically-do-brew-cleanup-36bi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Seriously, periodically do brew cleanup.&lt;/h2&gt;
      &lt;h3&gt;Collapsed PLUG ・ Nov 13 '18 ・ 1 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#homebrew&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;But since I want to actually figure out if there's programs I've installed and no longer use or need, I &lt;em&gt;could&lt;/em&gt; read the output of &lt;code&gt;brew list&lt;/code&gt; and &lt;code&gt;brew uninstall &amp;lt;package name&amp;gt;&lt;/code&gt; for each one, but I'm bound to overlook some packages that are dependencies, and may no longer be needed.&lt;/p&gt;

&lt;p&gt;I find it best to read visual "maps" that diagram the relationships between packages, so that if I uninstall a package that as a dependency on another package, and nobody else depends on that package, that I uninstall them both, thereby freeing up more resources.&lt;/p&gt;

&lt;p&gt;A nice helper program for Homebrew is this extension called &lt;code&gt;brew-graph&lt;/code&gt;: &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/martido"&gt;
        martido
      &lt;/a&gt; / &lt;a href="https://github.com/martido/homebrew-graph"&gt;
        homebrew-graph
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Creates a simple dependency graph of Homebrew formulae.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;strong&gt;Attention:&lt;/strong&gt; This repository has been renamed from &lt;code&gt;brew-graph&lt;/code&gt; to &lt;code&gt;homebrew-graph&lt;/code&gt; to adhere to the Homebrew naming conventions of &lt;a href="https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap" rel="nofollow"&gt;tap repositories&lt;/a&gt;
Please update your local clones or forks (for consistency only, GitHub makes sure everything still works for you):&lt;/p&gt;
&lt;div class="snippet-clipboard-content position-relative"&gt;&lt;pre&gt;&lt;code&gt;git remote set-url origin https://github.com/martido/homebrew-graph
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;
brew-graph&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;brew-graph&lt;/code&gt; is a Ruby script that creates a dependency graph of Homebrew formulae. The currently supported output options are &lt;em&gt;DOT&lt;/em&gt; and &lt;em&gt;GraphML&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In general, if you'd like to know more about &lt;a href="http://blog.jpalardy.com/posts/untangling-your-homebrew-dependencies" rel="nofollow"&gt;Untangling Your Homebrew Dependencies&lt;/a&gt;, check out the blog post by Jonathan Palardy.&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;div class="snippet-clipboard-content position-relative"&gt;&lt;pre&gt;&lt;code&gt;brew tap martido/homebrew-graph
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you already have the brew-graph formula installed from &lt;a href="https://github.com/martido/homebrew-brew-graph"&gt;the old tap repository&lt;/a&gt;, uninstall it first:&lt;/p&gt;
&lt;div class="snippet-clipboard-content position-relative"&gt;&lt;pre&gt;&lt;code&gt;brew uninstall brew-graph
brew untap martido/homebrew-brew-graph
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;Type &lt;code&gt;brew graph --help&lt;/code&gt;.&lt;/p&gt;
&lt;div class="snippet-clipboard-content position-relative"&gt;
&lt;pre&gt;&lt;code&gt;brew graph [options] formula1 formula2 ... | --installed | --all
Create a dependency graph of Homebrew formulae.

Options:

 -h, --help            Print this help message.
 -f, --format&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/martido/homebrew-graph"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Once installed (read the &lt;code&gt;README&lt;/code&gt;), I can create an image, along with the &lt;code&gt;graphviz&lt;/code&gt; package's &lt;code&gt;dot&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew graph &lt;span class="nt"&gt;--installed&lt;/span&gt; | dot &lt;span class="nt"&gt;-Tsvg&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; homebrew-installed.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I could replace the &lt;code&gt;svg&lt;/code&gt; part with &lt;code&gt;png&lt;/code&gt; to get a static image - I like the &lt;a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics"&gt;SVG file&lt;/a&gt; format, since it opens in Google Chrome and I can run a "Find" function for any names, and could also change some of the variables if I wanted to via text editor, or with an SVG Editor &lt;/p&gt;

&lt;p&gt;The image output is similar to the one in the header of this post - some items are isolated and appear at the top row - these packages have no dependencies, and nothing depends on them - often a tool to do a specific thing. Audit these for tools you use directly, and uninstall those that you don't recall using. You can always reinstall them later!&lt;/p&gt;

&lt;p&gt;Now for the more complex ones - like &lt;code&gt;ffmpeg&lt;/code&gt; for example. This package has a &lt;em&gt;lot&lt;/em&gt; of direct dependencies. So if I wanted to create an image that is scoped only to that package, I could run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew graph ffmpeg | dot &lt;span class="nt"&gt;-Tpng&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; homebrew-ffmpeg.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And that looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h-ZiIsUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ikcbkhyp1vajl7a744ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h-ZiIsUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ikcbkhyp1vajl7a744ey.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which isn't easy to see, but it can be helpful to see the dependencies of a single package.&lt;br&gt;
So if I wanted to uninstall all of the packages safely, I could run each one and if I get a warning that the package is in use, not remove it, or I could use another helpful external command - &lt;code&gt;rmtree&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/beeftornado"&gt;
        beeftornado
      &lt;/a&gt; / &lt;a href="https://github.com/beeftornado/homebrew-rmtree"&gt;
        homebrew-rmtree
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Remove a formula and its unused dependencies
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
homebrew-rmtree&lt;/h1&gt;
&lt;p&gt;Remove a formula and its unused dependencies&lt;/p&gt;
&lt;h2&gt;
What is it?&lt;/h2&gt;
&lt;p&gt;It's an &lt;a href="https://github.com/mxcl/homebrew/wiki/External-Commands"&gt;external command&lt;/a&gt; for &lt;a href="https://github.com/mxcl/homebrew"&gt;Homebrew&lt;/a&gt; that provides a new command, &lt;code&gt;rmtree&lt;/code&gt;
that will uninstall that formula, and uninstall any of its dependencies
that have no formula left installed that depend on them. The command will check all dependencies
recursively starting at the one specified on the command line.&lt;/p&gt;
&lt;p&gt;This is tricky business. So this command comes with a warning.&lt;/p&gt;
&lt;h3&gt;
Warning&lt;/h3&gt;
&lt;p&gt;There are formulae that do not specify all of their dependencies. This means that it is possible that
this command will remove something you still need or won't remove something you no longer want. Generally, it is pretty good
Until someone comes up with a clever way around this, you need to be careful what you uninstall
A formula could also depend on something you want to keep around, while nothing else actually
depends on it (except…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/beeftornado/homebrew-rmtree"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;This provides a useful &lt;code&gt;--dry-run&lt;/code&gt; parameter to observe what might happen if we wanted to remove a package, and see for ourselves what we would be removing. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew rmtree &lt;span class="nt"&gt;--dry-run&lt;/span&gt; ffmpeg
This is a dry-run, nothing will be deleted
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; Examining installed formulae required by ffmpeg...
 -  61 / 62

Can safely be removed
&lt;span class="nt"&gt;----------------------&lt;/span&gt;
ffmpeg
aom
lame
libbluray
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This goes on for a while, so run it yourself and see what your computer can safely remove!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reminder:&lt;/strong&gt; As always, take these notes with caution. The risk of installing someone else's software on systems that may lead to undue exposure. This post and other software are things lot of us write, but there's nothing preventing malicious actors from doing nasty things over similar channels, so make sure you have other protections in place - like firewalls, malware/virus scanners, network monitoring/alerting, etc - and if it's open source code, you can read it too, and form your own opinions!&lt;/p&gt;

&lt;p&gt;Hopefully this post has provided you with a couple of tools in your toolbox to help keep your computer in good shape, extending its lifespan and utility to keep learning and trying out new things!&lt;/p&gt;

</description>
      <category>homebrew</category>
      <category>macos</category>
    </item>
    <item>
      <title>Python to JSON and Back</title>
      <dc:creator>Mike Fiedler</dc:creator>
      <pubDate>Fri, 24 Apr 2020 00:33:36 +0000</pubDate>
      <link>https://dev.to/miketheman/python-to-json-and-back-17a4</link>
      <guid>https://dev.to/miketheman/python-to-json-and-back-17a4</guid>
      <description>&lt;p&gt;&lt;cite&gt;Photo by &lt;a href="https://unsplash.com/@davidclode?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;David Clode&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/python?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;As JavaScript Object Notation (&lt;a href="https://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt;) has become the ubiquitous language of communication between APIs on the web, being able to take &lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; objects and serialize them to JSON strings is an important part of communicating with other services, clients, APIs, what have you.&lt;/p&gt;

&lt;p&gt;The default Python &lt;a href="https://docs.python.org/3/library/json.html"&gt;&lt;code&gt;json&lt;/code&gt;&lt;/a&gt; module supports both &lt;a href="https://docs.python.org/3/library/json.html#json.dump"&gt;&lt;code&gt;dump&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.python.org/3/library/json.html#json.dumps"&gt;&lt;code&gt;dumps&lt;/code&gt;&lt;/a&gt; methods - the more common one used is &lt;code&gt;dumps&lt;/code&gt; - dumping the object to a JSON String - all based on this &lt;a href="https://docs.python.org/3/library/json.html#py-to-json-table"&gt;Conversion Table&lt;/a&gt; - which pointedly omits the &lt;code&gt;datetime&lt;/code&gt; objects - most importantly because the &lt;a href="https://www.json.org/"&gt;JSON Specification&lt;/a&gt; has no reference to any specific date/time format.&lt;br&gt;
This is left up to the implementer, based on what format they need - leaving coders everywhere figuring out how to Do The Right Thing - since any date/time mismatches have potential to cause all manner of havoc if incorrectly parsed. If you want to read more on time, check out &lt;a href="https://github.com/kdeldycke/awesome-falsehood#dates-and-time"&gt;this collection of articles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A simple demonstration of the failure condition looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;".../lib/python3.6/json/__init__.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;231&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dumps&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_default_encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;".../lib/python3.6/json/encoder.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;199&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;
    &lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iterencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_one_shot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;".../lib/python3.6/json/encoder.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;257&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;iterencode&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_iterencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;".../3.6.8/lib/python3.6/json/encoder.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
    &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="s"&gt;'datetime'&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt; &lt;span class="n"&gt;serializable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And if you've hit this, and search the internet, you'll find all manner of approaches to resolve - a common approach seen is &lt;a href="https://stackoverflow.com/a/3235787"&gt;implementing a function&lt;/a&gt; that iterates through an object, and if it finds a &lt;code&gt;datetime&lt;/code&gt; value, convert it to the &lt;a href="https://www.iso.org/iso-8601-date-and-time-format.html"&gt;ISO 8601&lt;/a&gt; format, with &lt;a href="https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat"&gt;&lt;code&gt;datetime.isoformat()&lt;/code&gt;&lt;/a&gt;. Example of the conversion step:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="s"&gt;'"2020-04-23T23:36:36.620619"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However this then becomes custom code to iterate through objects, and sometimes we may need to iterate through deeply nested objects - for example a blog page, its posts and comments in a single JSON payload may all have timestamps that would need to be iterated through, detected, converted, and then &lt;code&gt;json.dumps()&lt;/code&gt; the whole thing.&lt;/p&gt;

&lt;p&gt;Some popular frameworks may handle this for you automatically - notable callouts are the Django REST Framework &lt;a href="https://www.django-rest-framework.org/api-guide/fields/#datetimefield"&gt;&lt;code&gt;DateTimeField&lt;/code&gt;&lt;/a&gt; will default to ISO8601, as will the excellent &lt;a href="https://pydantic-docs.helpmanual.io/"&gt;&lt;code&gt;pydantic&lt;/code&gt;&lt;/a&gt; library (here's the &lt;a href="https://github.com/samuelcolvin/pydantic/blob/cab6313798765d634e97e3a923c48dfe64367775/pydantic/json.py#L16-L17"&gt;implementation under the hood&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;However, oftentimes we may not want to take on importing a framework or a full-fledged library, but still want to avoid having to create custom solutions like this - and that's where we can lean on well-trodden paths from library maintainers, like the &lt;a href="https://rapidjson.org/"&gt;&lt;code&gt;rapidjson&lt;/code&gt;&lt;/a&gt; library - and more importantly, the &lt;a href="https://python-rapidjson.readthedocs.io/"&gt;Python wrapper to this fast C library&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;rapidjson&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rapidjson&lt;/code&gt; aims to be a swap-in replacement for the native Python &lt;code&gt;json&lt;/code&gt; module, and allows the coder to extend the behavior to support more behaviors with less effort. &lt;strong&gt;Note:&lt;/strong&gt; This package must be installed via the &lt;a href="https://pypi.org/project/python-rapidjson/"&gt;&lt;code&gt;python-rapidjson&lt;/code&gt;&lt;/a&gt; package name.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Keep in mind:&lt;/em&gt; there are a &lt;a href="https://python-rapidjson.readthedocs.io/en/latest/quickstart.html#incompatibilities"&gt;few incompatibilities&lt;/a&gt; you should be aware of when using &lt;code&gt;rapidjson&lt;/code&gt; - but most implementations may not be using these, in fact the coercion of &lt;code&gt;"true"&lt;/code&gt; strings to Python &lt;code&gt;True&lt;/code&gt; values is actually an improvement!&lt;/p&gt;

&lt;p&gt;So if we were to run our example from above, replacing &lt;code&gt;json&lt;/code&gt; with &lt;code&gt;rapidjson&lt;/code&gt;, we get the same result, albeit the traceback is a little clearer now:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;rapidjson&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rapidjson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105719&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt; &lt;span class="n"&gt;serializable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However now we can pass an argument to &lt;code&gt;rapidjson.dumps()&lt;/code&gt; to inform it how we want to handle &lt;code&gt;datetime&lt;/code&gt; instances, like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rapidjson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;datetime_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rapidjson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DM_ISO8601&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;'"2020-04-24T00:14:35.531078"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Voilá, we've got a valid ISO8601-formatted string of a &lt;code&gt;datetime&lt;/code&gt; with little added!&lt;/p&gt;

&lt;p&gt;I've put together a more complete example of full object deserialization and loading below - feel free to run, fork, extend, experiment with the code, and read more about the &lt;a href="https://python-rapidjson.readthedocs.io/en/latest/dumps.html#dumps-datetime-mode"&gt;other &lt;code&gt;datetime_mode&lt;/code&gt; options in &lt;code&gt;rapidjson&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@miketheman/TartUsablePipelining?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



</description>
      <category>python</category>
      <category>json</category>
      <category>api</category>
      <category>rapidjson</category>
    </item>
  </channel>
</rss>
