
    
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
            
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/tags\/json","feed_url":"https:\/\/mathspp.com\/blog\/tags\/json.json","description":"Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com.","author":{"name":"Rodrigo Gir\u00e3o Serr\u00e3o"},"items":[{"title":"TIL #049 \u2013 edit multiple file locations in VS Code","date_published":"2022-07-31T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/edit-multiple-file-locations-in-vscode","url":"https:\/\/mathspp.com\/blog\/til\/edit-multiple-file-locations-in-vscode","content_html":"<p>Today I learned how to edit multiple lines in the VS Code code editor.<\/p>\n\n<p><img alt=\"A GIF animation showing multiple cursors being put in a VS Code editor window and then some changes being typed into all locations at once.\" src=\"\/user\/pages\/02.blog\/04.til\/049.edit-multiple-file-locations-in-vscode\/_editing_multiple_locations_in_vscode.gif?decoding=auto&amp;fetchpriority=auto\"><\/p>\n<h2 id=\"how-to-edit-multiple-file-locations-in-vs-code\">How to edit multiple file locations in VS Code?<a href=\"#how-to-edit-multiple-file-locations-in-vs-code\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Inside VS Code, if you hold <kbd>Ctrl<\/kbd> while clicking different lines with your mouse left button,\nyou will place multiple cursors.\nThen, you can start typing and those changes will affect all the locations you clicked.<\/p>\n<h2 id=\"how-to-edit-multiple-lines-in-vs-code\">How to edit multiple lines in VS Code?<a href=\"#how-to-edit-multiple-lines-in-vs-code\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>With this keyboard shortcut, you can hold <kbd>Ctrl<\/kbd> and click the end of multiple lines to edit them all at once.<\/p>\n<p>That's it for now! <a href=\"\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned how to edit multiple lines in the VS Code code editor.","date_modified":"2025-07-23T16:49:02+02:00","tags":["json","programming","python","vscode"],"image":"\/user\/pages\/02.blog\/04.til\/049.edit-multiple-file-locations-in-vscode\/thumbnail.webp"},{"title":"Custom JSON encoder and decoder","date_published":"2022-06-20T17:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/custom-json-encoder-and-decoder","url":"https:\/\/mathspp.com\/blog\/custom-json-encoder-and-decoder","content_html":"<p>This article explains how to extend the JSON format by using a custom encoder and a custom decoder to turn arbitrary Python objects into JSON and back.<\/p>\n\n<p><img alt=\"There is a blurry background that looks like a tunnel, but in front of that you can find the JSON and the Python logos, with two arrows pointing in each direction, giving a sense of interchangeability.\" src=\"\/images\/8\/4\/c\/f\/f\/84cffcf37c06d63dda8f033d02de61ef5d3408f5-thumbnail.webp\"><\/p>\n<h2 id=\"custom-json-encoder-and-decoder\">Custom JSON encoder and decoder<a href=\"#custom-json-encoder-and-decoder\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The Python module <code>json<\/code> allows you to work with the JSON data format.\nIn previous articles,\nI've written about doing <a href=\"\/blog\/til\/custom-json-encoder\">custom JSON encoding<\/a> of arbitrary Python objects\nand <a href=\"\/blog\/til\/custom-json-decoder-part-2\">custom JSON decoding<\/a> <em>into<\/em> arbitrary Python objects.<\/p>\n<p>In this article I want to define a system that makes it easy to extend the JSON format,\nso that we can encode more Python objects into JSON and back.<\/p>\n<p>My goal is to define a mechanism through which you can easily define small, atomic encoders and decoders,\nand to have them all operate together.<\/p>\n<h2 id=\"extending-the-json-format\">Extending the JSON format<a href=\"#extending-the-json-format\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>I think it will be easier to understand what I want to achieve if I show you how I want the end product to look like.<\/p>\n<p>Suppose that you want to extend the JSON format so that you can also encode and decode complex numbers and Python <code>range<\/code> objects.\nThis is what you want to do.\nHow do you achieve that?<\/p>\n<p>When you are done with the article, you will be able to define something like this:<\/p>\n<pre><code class=\"language-py\">class ComplexAndRangeEncoder(...):\n    def encode_complex(self, c):\n        return {\"real\": c.real, \"imag\": c.imag}\n\n    def encode_range(self, r):\n        return {\"start\": r.start, \"stop\": r.stop, \"step\": r.step}\n\nclass ComplexAndRangeDecoder(...):\n    def decode_complex(self, obj):\n        return complex(obj[\"real\"], obj[\"imag\"])\n\n    def decode_range(self, obj):\n        return range(obj[\"start\"], obj[\"stop\"], obj[\"step\"])<\/code><\/pre>\n<p>Then, you will be able to use these two classes as the <code>cls<\/code> argument to the <code>json<\/code> methods,\nenabling you to encode complex numbers and ranges to JSON, and then decoding them back.<\/p>\n<p>The point, here, is that I want to make it as easy as possible to extend the JSON standard,\nsimply by providing the encoders and the decoders for each new type you want to be able to handle.<\/p>\n<h2 id=\"automatically-recognising-non-standard-json\">Automatically recognising non-standard JSON<a href=\"#automatically-recognising-non-standard-json\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The main issue I have to struggle with is in defining the mechanism that will allow the custom JSON decoder to recognise that certain JSON objects should actually be parsed into something else.\nFor example, in the previous <a href=\"\/blog\/til\/custom-json-decoder-part-2\">article about custom JSON decoding<\/a>,\nI showed how to convert the following JSON:<\/p>\n<pre><code class=\"language-json\">{\n    \"real\": 1.0,\n    \"imag\": 2.0\n}<\/code><\/pre>\n<p>into the Python complex number <span class=\"mathjax mathjax--inline\">\\(1 + 2i\\)<\/span>:<\/p>\n<pre><code class=\"language-py\">(1+2j)<\/code><\/pre>\n<p>However, suppose that we actually have the following Python dictionary:<\/p>\n<pre><code class=\"language-py\">dict_looks_like_complex = {\n    \"real\": 1.0,\n    \"imag\": 2.0,\n}<\/code><\/pre>\n<p>If we convert this dictionary to JSON, we get a string:<\/p>\n<pre><code class=\"language-json\">'{\"real\": 1.0, \"imag\": 2.0}'<\/code><\/pre>\n<p>Now, if we use our custom decoder, we will get a complex number back instead of the original dictionary!\nWhy?\nBecause complex numbers and some dictionaries have the same JSON representations.<\/p>\n<div class=\"notices yellow\">\n<p>In mathematical terms, we say that the JSON encoding is not injective.\nAfter all, I can find two objects <code>obj1<\/code> and <code>obj2<\/code> such that <code>obj1 != obj2<\/code> and yet\n<code>json.dumps(obj1) == json.dumps(obj2)<\/code>.<\/p>\n<\/div>\n<p>We have two options here:<\/p>\n<ul><li>assume these collisions aren't troublesome and decide to not worry about them; or<\/li>\n<li>try to tweak the...<\/li><\/ul>","summary":"This article explains how to extend the JSON format by using a custom encoder and a custom decoder to turn arbitrary Python objects into JSON and back.","date_modified":"2025-07-23T16:49:02+02:00","tags":["json","programming","python"],"image":"\/user\/pages\/02.blog\/custom-json-encoder-and-decoder\/thumbnail.webp"},{"title":"TIL #048 \u2013 custom JSON decoder, part 2","date_published":"2022-06-20T10:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/custom-json-decoder-part-2","url":"https:\/\/mathspp.com\/blog\/til\/custom-json-decoder-part-2","content_html":"<p>Today I finished learning how to use a custom JSON decoder to convert JSON to arbitrary Python objects.<\/p>\n\n<p><img alt=\"A solid background with an arrow pointing to some faded gears behind the words &ldquo;JSON Decoder&rdquo;, which then have an arrow pointing to the Python logo.\" src=\"\/images\/3\/e\/0\/4\/0\/3e0406998371d120d1868896120b6c55823beb54-thumbnail.webp\"><\/p>\n<h2 id=\"asymmetry-suggests-other-alternatives\">Asymmetry suggests other alternatives<a href=\"#asymmetry-suggests-other-alternatives\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>In the two previous TIL articles,\nI wrote briefly about how to <a href=\"\/blog\/til\/custom-json-encoder\">use a custom JSON encoder<\/a>\nand how to <a href=\"\/blog\/til\/custom-json-decoder\">use a custom JSON decoder<\/a>.\nLooking at the two articles linked,\nthere is a noticeable asymmetry in the strategies used to do the encoding and the decoding.<\/p>\n<p>We subclassed <code>json.JSONEncoder<\/code> in order to <a href=\"\/blog\/til\/custom-json-encoder#custom-json-encoding-of-python-objects\">implement custom JSON encoding for our Python objects<\/a>,\nand then we passed that class to the methods <code>json.dump<\/code> and <code>json.dumps<\/code>.\nHowever, in order to <a href=\"\/blog\/til\/custom-json-decoder#custom-json-decoding-into-arbitrary-python-objects\">implement custom JSON decoding into arbitrary Python objects<\/a>,\nwe just implemented a function that was then passed into <code>json.load<\/code> and <code>json.loads<\/code> as the parameter <code>object_hook<\/code>.<\/p>\n<p>Reading the two previous sentences, even if I didn't know the module <code>json<\/code>,\nI would expect one of the two to be true:<\/p>\n<ul><li>there is a class <code>json.JSONDecoder<\/code> that can be subclassed and then passed in to <code>json.load<\/code> and <code>json.loads<\/code>,\nwhich will also allow for custom JSON decoding; or<\/li>\n<li>\n<code>json.dump<\/code> and <code>json.dumps<\/code> accept a parameter which should have a name similar to <code>encode_hook<\/code> or <code>encoder_hook<\/code>,\nwhich would allow us to implement just a function that would take care of the custom JSON encoding.<\/li>\n<\/ul><p>As it turns out, the former is true:\nthe module <code>json<\/code> has a class <code>JSONDecoder<\/code> that we can subclass &ndash; and then feed to <code>json.load<\/code> and <code>json.loads<\/code> &ndash;\nwhich allows us to decode JSON into arbitrary Python objects.\nLet us see how to do that.<\/p>\n<h2 id=\"json-jsondecoder\"><code>json.JSONDecoder<\/code><a href=\"#json-jsondecoder\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The documentation doesn't tell you much about <a href=\"https:\/\/docs.python.org\/3\/library\/json.html#json.JSONDecoder\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">how to use <code>json.JSONDecoder<\/code><\/a>,\nso I will share with you what I could piece together.<\/p>\n<p>The functions <code>json.load<\/code> and <code>json.loads<\/code> accept a keyword argument <code>cls<\/code>,\nwhich the documentation describes as behaving in the following way:<\/p>\n<blockquote>\n<p>&ldquo;To use a custom <code>JSONDecoder<\/code> subclass, specify it with the <code>cls<\/code> kwarg; otherwise <code>JSONDecoder<\/code> is used. Additional keyword arguments will be passed to the constructor of the class.&rdquo;<\/p>\n<\/blockquote>\n<p>Then, if you go and read the documentation on <code>JSONDecoder<\/code>,\nyou see that it accepts an <code>object_hook<\/code> upon initialisation,\nwhich is what we have used to implement <a href=\"\/blog\/til\/custom-json-decoder#custom-json-decoding-into-arbitrary-python-objects\">custom JSON decoding<\/a> in the previous article.<\/p>\n<p>Thus, the obvious path forward seems to be to subclass <code>json.JSONDecoder<\/code> and make it so that,\nby default, it uses a custom <code>object_hook<\/code> argument.<\/p>\n<p>Something along the lines of this blueprint:<\/p>\n<pre><code class=\"language-py\">import json\n\nclass MyJSONDecoder(json.JSONDecoder):\n    def __init__(self, **kwargs):\n        kwargs.setdefault(\"object_hook\", my_custom_object_hook)\n        # Just need to implement this ---^^^^^^^^^^^^^^^^^^^^^\n        super().__init__(**kwargs)\n\nmy_object = json.loads(json_data, cls=MyJSONDecoder)<\/code><\/pre>\n<h2 id=\"defining-a-custom-decoder-class\">Defining a custom decoder class<a href=\"#defining-a-custom-decoder-class\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>With the blueprint above in mind, let us go back to the example of decoding complex numbers.<\/p>\n<p>Let us assume that a complex number is represented as a JSON dictionary with the following structure:<\/p>\n<pre><code class=\"language-json\">{\n    \"real\": 1.0,\n    \"imag\": 2.0\n}<\/code><\/pre>\n<p>Taking that into account, we can implement the object hook as follows:<\/p>\n<pre><code class=\"language-py\">import json\n\nclass ComplexDecoder(json.JSONDecoder):\n    def __init__(self, **kwargs):\n        kwargs.setdefault(\"object_hook\", self.object_hook)\n        super().__init__(**kwargs)\n\n    def object_hook(self, dict_):\n        \"\"\"Try to decode a complex number.\"\"\"\n        try:\n            return complex(dict_[\"real\"], dict_[\"imag\"])...<\/code><\/pre>","summary":"Today I finished learning how to use a custom JSON decoder to convert JSON to arbitrary Python objects.","date_modified":"2025-07-23T16:49:02+02:00","tags":["json","programming","python"],"image":"\/user\/pages\/02.blog\/04.til\/048.custom-json-decoder-part-2\/thumbnail.webp"},{"title":"TIL #047 \u2013 custom JSON decoder","date_published":"2022-06-04T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/custom-json-decoder","url":"https:\/\/mathspp.com\/blog\/til\/custom-json-decoder","content_html":"<p>Today I learned how to do custom JSON decoding in Python with the module <code>json<\/code>.<\/p>\n\n<p><img alt=\"A solid background with an arrow going from a JSON logo into the Python logo.\" src=\"\/images\/6\/0\/1\/c\/2\/601c27006d0b78c0aebe54c6778d1931bac6b93f-thumbnail.webp\"><\/p>\n<h2 id=\"how-to-decode-python-objects-as-json\">How to decode Python objects as JSON<a href=\"#how-to-decode-python-objects-as-json\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The module <code>json<\/code> is your go-to tool whenever you need to work with JSON data in Python.\nMuch like you have the methods <code>json.dump<\/code> and <code>json.dumps<\/code> to turn Python objects into JSON,\nyou can use the methods <code>json.load<\/code> and <code>json.loads<\/code> to turn JSON into Python.<\/p>\n<p>By using <code>json.loads<\/code>,\nyou can take a JSON string and turn it into a valid Python object:<\/p>\n<pre><code class=\"language-py\">import json\n\nstring = '[42, {\"key\": null, \"other_key\": false}]'\n\nprint(json.loads(string))<\/code><\/pre>\n<pre><code class=\"language-py\">[42, {'key': None, 'other_key': False}]<\/code><\/pre>\n<p>The method <code>json.load<\/code> comes in handy if you have a file (or something similar) to read the data from.<\/p>\n<p>You can read more about <code>json<\/code>, <code>json.load<\/code>, and <code>json.loads<\/code> <a href=\"https:\/\/docs.python.org\/3\/library\/json.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">in the <code>json<\/code> documentation<\/a>.<\/p>\n<p>If you want to take a look at how to <strong>encode<\/strong> Python as JSON,\ntake a look at the TIL about <a href=\"\/blog\/til\/custom-json-encoder\">custom JSON encoding of Python objects<\/a>.<\/p>\n<p>Because we <strong>cannot encode arbitrary Python objects as JSON<\/strong> by default,\nwe <a href=\"\/blog\/til\/custom-json-encoder\">implement custom JSON encoders<\/a> to work around that.<\/p>\n<p>The reverse side of that coin is that we must be able to decode those objects again.\nHowever, the module <code>json<\/code> cannot guess what custom encodings we may have done,\nso we need to <strong>specify our custom decodings<\/strong> when appropriate.<\/p>\n<p>But first, let us take a look at what the module <code>json<\/code> does in its default decoding.<\/p>\n<h2 id=\"default-json-decoding-into-python-objects\">Default JSON decoding into Python objects<a href=\"#default-json-decoding-into-python-objects\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>According to <a href=\"https:\/\/docs.python.org\/3\/library\/json.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">the <code>json<\/code> docs<\/a>,\nthis is what the default decoding does:<\/p>\n<table><thead><tr><th style=\"text-align: left;\">JSON<\/th>\n<th style=\"text-align: left;\">Python<\/th>\n<\/tr><\/thead><tbody><tr><td style=\"text-align: left;\">object<\/td>\n<td style=\"text-align: left;\"><code>dict<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">array<\/td>\n<td style=\"text-align: left;\"><code>list<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">string<\/td>\n<td style=\"text-align: left;\"><code>str<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">number (integer)<\/td>\n<td style=\"text-align: left;\"><code>int<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">number (real)<\/td>\n<td style=\"text-align: left;\"><code>float<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">true<\/td>\n<td style=\"text-align: left;\"><code>True<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">false<\/td>\n<td style=\"text-align: left;\"><code>False<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">null<\/td>\n<td style=\"text-align: left;\"><code>None<\/code><\/td>\n<\/tr><\/tbody><\/table><p>Thus, if you want to obtain, as a Python object,\nanything that is not on the right column,\nyou need to <strong>implement a custom JSON decoder<\/strong>.<\/p>\n<h2 id=\"custom-json-decoding-into-arbitrary-python-objects\">Custom JSON decoding into arbitrary Python objects<a href=\"#custom-json-decoding-into-arbitrary-python-objects\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>We have two mechanisms that let us do custom JSON decoding.\nBy taking a look at the <a href=\"https:\/\/docs.python.org\/3\/library\/json.html#json.load\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\"><code>json.load<\/code> documentation<\/a>,\nwe see that we care about the keyword-arguments <code>object_hook<\/code> and <code>object_pairs_hook<\/code>.\nLet us play with <code>object_hook<\/code> a bit.<\/p>\n<p>The function you provide as the <code>object_hook<\/code> argument is a function that:<\/p>\n<ul><li>will be called whenever the JSON decoding process builds a dictionary (a Python <code>dict<\/code>); and<\/li>\n<li>must return the Python object to be used in place of the dictionary that was built.<\/li>\n<\/ul><p>In essence, the function you provide as the <code>object_hook<\/code> will be &ldquo;intercepting&rdquo; the decoding process,\nand you can use it to build custom objects!<\/p>\n<p>Going back to the example where we <a href=\"\/blog\/til\/custom-json-encoder#custom-json-encoding-of-python-objects\">used a custom JSON encoder for complex numbers<\/a>,\nnow we may want to let our code know how to <strong>decode complex numbers<\/strong>.\nIn other words, we might want to do the reverse process.<\/p>\n<p>So, we want to go from:<\/p>\n<pre><code class=\"language-json\">{\n    \"real\": 2,\n    \"imag\": 3\n}<\/code><\/pre>\n<p>to the complex number<\/p>\n<pre><code class=\"language-py\">2+3j  # also represented as complex(2, 3)<\/code><\/pre>\n<p>We start by defining our object hook function,\nand use it to recognise dictionaries...<\/p>","summary":"Today I learned how to use a custom JSON decoder in Python with the module `json`.","date_modified":"2025-07-23T16:49:02+02:00","tags":["json","programming","python"],"image":"\/user\/pages\/02.blog\/04.til\/047.custom-json-decoder\/thumbnail.webp"},{"title":"TIL #046 \u2013 custom JSON encoder","date_published":"2022-06-03T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/custom-json-encoder","url":"https:\/\/mathspp.com\/blog\/til\/custom-json-encoder","content_html":"<p>Today I learned how to do custom JSON encoding in Python with the module <code>json<\/code>.<\/p>\n\n<p><img alt=\"A solid background with an arrow going from the Python logo to a JSON logo.\" src=\"\/user\/pages\/02.blog\/04.til\/046.custom-json-encoder\/thumbnail.webp\"><\/p>\n<h2 id=\"how-to-encode-python-objects-as-json\">How to encode Python objects as JSON<a href=\"#how-to-encode-python-objects-as-json\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>In Python, we use the module <code>json<\/code> whenever we need to work with JSON data.\nThis module makes it very easy to do so,\nby means of the methods <code>json.dump<\/code> and <code>json.dumps<\/code>.<\/p>\n<p>By using <code>json.dumps<\/code>, we can get a JSON document as a string,\nbased on the Python object we give it:<\/p>\n<pre><code class=\"language-py\">import json\n\ndata = {\n    \"one_key\": 73,\n    \"other_key\": [\n        True,\n        False,\n        None,\n    ]\n}\n\nprint(json.dumps(data))<\/code><\/pre>\n<pre><code class=\"language-txt\">{\"one_key\": 73, \"other_key\": [true, false, null]}<\/code><\/pre>\n<p>The method <code>json.dump<\/code> is useful when you have a file you want to write the JSON to.<\/p>\n<p>You can read more about <code>json<\/code>, <code>json.dump<\/code>, and <code>json.dumps<\/code> <a href=\"https:\/\/docs.python.org\/3\/library\/json.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">in the <code>json<\/code> documentation<\/a>.<\/p>\n<p>Despite being quite useful, the module <code>json<\/code> has its limitations,\nespecially ones derived from the JSON standard itself.\nFor example, the JSON standard doesn't tell you how to handle complex numbers,\nand so the module <code>json<\/code> doesn't know how to deal with them:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; import json\n&gt;&gt;&gt; json.dumps(complex(2, 3))\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\n  File \"C:\\Program Files\\Python39\\lib\\json\\__init__.py\", line 231, in dumps\n    return _default_encoder.encode(obj)\n  File \"C:\\Program Files\\Python39\\lib\\json\\encoder.py\", line 199, in encode\n    chunks = self.iterencode(o, _one_shot=True)\n  File \"C:\\Program Files\\Python39\\lib\\json\\encoder.py\", line 257, in iterencode\n    return _iterencode(o, 0)\n  File \"C:\\Program Files\\Python39\\lib\\json\\encoder.py\", line 179, in default\n    raise TypeError(f'Object of type {o.__class__.__name__} '\nTypeError: Object of type complex is not JSON serializable<\/code><\/pre>\n<p>So, what can the module <code>json<\/code> handle?<\/p>\n<h2 id=\"default-json-conversion-of-python-objects\">Default JSON conversion of Python objects<a href=\"#default-json-conversion-of-python-objects\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>According to <a href=\"https:\/\/docs.python.org\/3\/library\/json.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">the <code>json<\/code> docs<\/a>,\nthese are the types supported by default:<\/p>\n<table><thead><tr><th style=\"text-align: left;\">Python<\/th>\n<th style=\"text-align: left;\">JSON<\/th>\n<\/tr><\/thead><tbody><tr><td style=\"text-align: left;\"><code>dict<\/code><\/td>\n<td style=\"text-align: left;\">object<\/td>\n<\/tr><tr><td style=\"text-align: left;\">\n<code>list<\/code>, <code>tuple<\/code>\n<\/td>\n<td style=\"text-align: left;\">array<\/td>\n<\/tr><tr><td style=\"text-align: left;\"><code>str<\/code><\/td>\n<td style=\"text-align: left;\">string<\/td>\n<\/tr><tr><td style=\"text-align: left;\">\n<code>int<\/code>, <code>float<\/code>, <code>int<\/code>- &amp; <code>float<\/code>-derived Enums<\/td>\n<td style=\"text-align: left;\">number<\/td>\n<\/tr><tr><td style=\"text-align: left;\"><code>True<\/code><\/td>\n<td style=\"text-align: left;\">true<\/td>\n<\/tr><tr><td style=\"text-align: left;\"><code>False<\/code><\/td>\n<td style=\"text-align: left;\">false<\/td>\n<\/tr><tr><td style=\"text-align: left;\"><code>None<\/code><\/td>\n<td style=\"text-align: left;\">null<\/td>\n<\/tr><\/tbody><\/table><p>If you want to convert anything that is not on the left column of that table,\nyou need to implement your own custom JSON encoder.<\/p>\n<h2 id=\"custom-json-encoding-of-python-objects\">Custom JSON encoding of Python objects<a href=\"#custom-json-encoding-of-python-objects\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>If you want to do custom JSON encoding of Python objects that are not included in the table above,\nyou will need to subclass <code>json.JSONEncoder<\/code> and you will need to override the method <code>.default<\/code>.<\/p>\n<p>The method <code>json.JSONEncoder.default<\/code> is called for each object that the module <code>json<\/code> doesn't know how to encode by default.<\/p>\n<p>For example, if you want to encode complex numbers in JSON, you could do this:<\/p>\n<pre><code class=\"language-py\">import json\n\nclass JSONComplexEncoder(json.JSONEncoder):\n    \"\"\"JSON encoder that also knows how to encode complex numbers.\"\"\"\n\n    def default(self, obj):\n        if isinstance(obj, complex):\n            return {\"real\": obj.real, \"imag\": obj.imag}\n\n        return super().default(obj)<\/code><\/pre>\n<div class=\"notices yellow\">\n<p>The reason we call <code>super().default(obj)<\/code> if the object provided isn't a complex number <a href=\"https:\/\/docs.python.org\/3\/library\/json.html#json.JSONEncoder.default\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">is explained in the docs<\/a>.\nEssentially, the base implementation is responsible for raising the <code>TypeError<\/code> when we fail to serialise an object.<\/p>\n<\/div>\n<p>Now that we have the class <code>JSONComplexEncoder<\/code>,\nwe can pass it in to the methods <code>json.dump<\/code> and <code>json.dumps<\/code>,\nso that they can use this custom encoder we defined:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; c = complex(2, 3)\n&gt;&gt;&gt; json.dumps(c, cls=JSONComplexEncoder)\n'{\"real\": 2.0, \"imag\":...<\/code><\/pre>","summary":"Today I learned how to use a custom JSON encoder in Python with the module `json`.","date_modified":"2025-07-23T16:49:02+02:00","tags":["json","programming","python"],"image":"\/user\/pages\/02.blog\/04.til\/046.custom-json-encoder\/thumbnail.webp"}]}
