title: json.dumps TypeError on Python dict
body: <p>The following class is implemented to provide a generic object that can be passed through network as a json-encoded dictionary. I'm actually trying to json encode a dict (!) but it won't work.</p>
  
  <p>I know it will work with custom encoder class, but I don't see why it's necessary when I'm just encoding a dict. </p>
  
  <p><strong>Can someone explain the TypeError or offer a way to encode this without subclassing JSONEncoder?</strong></p>
  
  <p>Here is the bad behavior. </p>
  
  <pre><code>&gt;&gt;&gt; def tree(): return CustomDict(tree)
  &gt;&gt;&gt; d = tree()
  &gt;&gt;&gt; d['one']['test']['four'] = 19
  &gt;&gt;&gt; d.dict
  { 'one' : { 'test': {'four': 19}}}
  &gt;&gt;&gt; type(d.dict)
  &lt;type 'dict'&gt; 
  &gt;&gt;&gt; import json
  &gt;&gt;&gt; json.dumps(d.dict)
  # stacktrace removed
  TypeError: {'one': {'test': {'four': 19}}} is not JSON serializable
  &gt;&gt;&gt; normal_d = {'one': {'test': {'four': 19}}}
  &gt;&gt;&gt; type(normal_d)
  &lt;type 'dict'&gt;
  &gt;&gt;&gt; json.dumps(normal_d)
  "{'one': {'test': {'four': 19}}}"
  &gt;&gt;&gt; normal_d == d
  True
  </code></pre>
  
  <p>I would love to be able to do the following </p>
  
  <pre><code>&gt;&gt;&gt;&gt; json.dumps(dict(d))
  "{'one': {'test': {'four': 19}}}"
  </code></pre>
  
  <p>but I added the dict property to 'force it' (didn't work obviously). Now it's an even bigger mystery. Here is the code for the CustomDict class</p>
  
  <pre><code>class CustomDict(collections.MutableMapping):                                
      """                                                                         
      A defaultdict-like object that can also have properties and special methods 
      """                                                                         
  
      def __init__(self, default_type=str, *args,  **kwargs):                     
          """                                                                     
          instantiate as a default-dict (str if type not provided). Try to update 
          self with each arg, and then update self with kwargs.                                                                
  
          @param default_type: the type of the default dict                       
          @type default_type: type (or class)                                     
          """                                                                     
          self._type = default_type                                               
          self._store = collections.defaultdict(default_type)                     
          self._dict = {}                                                         
  
          for arg in args:                                                        
              if isinstance(arg, collections.MutableMapping):                     
                  self.update(arg)                                                
  
          self.update(kwargs)                                                     
  
      @property                                                                   
      def dict(self):                                                             
          return self._dict                                                       
  
      def __contains__(self, key):                                                
          return key in self._store                                               
  
      def __len__(self):                                                          
          return len(self._store)                                                 
  
      def __iter__(self):                                                         
          return iter(self._store)                                                
  
      def __getitem__(self, key):                                                 
          self._dict[key] = self._store[key]                                      
          return self._store[key]                                                 
  
      def __setitem__(self, key, val):                                            
          self._dict[key] = val                                                   
          self._store[key] = val                                                  
  
      def __delitem__(self, key):                                                 
          del self._store[key]                                                    
  
      def __str__(self):                                                          
          return str(dict(self._store))   
  </code></pre>