title: How can I json-serialize a custom iterable?
body: <p>I'd like to create a type that behaves as a named tuple except that it has a custom representation, which is also respected when serialized as JSON.</p>
  
  <p>The naive by-the-books approach would be something like this:</p>
  
  <pre class="lang-python prettyprint-override"><code>from typing import NamedTuple
  import json
  
  
  class MyPair(NamedTuple):
      left: str
      right: str
  
      def __repr__(self):
          return self.left + ':' + self.right
  
  
  class MyJSONEncoder(json.JSONEncoder):
      def default(self, obj):
          if isinstance(obj, MyPair):
              return str(obj)
          return json.JSONEncoder.default(self, obj)
  </code></pre>
  
  <p>Now <code>print(MyPair('a', 'b'))</code> will output <code>a:b</code> as intended, but <code>print(json.dumps([MyPair('a', 'b')], cls=MyJSONEncoder))</code> will produce <code>[["a", "b"]]</code> because <code>default()</code> is only called if an object is not primitively serializable as JSON. Since my own type is a tuple, it will be serialized before I get a chance to intervene.</p>
  
  <p>Is there any nice or not-so-nice way of achieving this without making <code>MyPair</code> not a <code>Tuple</code> or iterating over the entire document in a preprocessing step that replaces all <code>MyPair</code> objects by strings?</p>
  
  <p><strong>Edit:</strong> To address Joran's answer, I still want to retain the ability to serialize complex trees that just <em>contain</em> the occasional <code>MyPair</code>s. My minimal example might not have made that clear, sorry.</p>