# Json does not support Mapping and MutableMapping

**URL:** <https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829>\
**Category:** Python Help\
**Created:** [December 10, 2019, 6:07pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829 "2019-12-10T18:07:27Z")\
**Posts on this page:** 10\
**Page:** 2

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [December 14, 2019, 4:51am UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/21 "2019-12-14T04:51:46Z")

</div>

> [@Marco\_Sulla](#):
>
> I suppose it does not break nothing, on the contrary. Simply `default` will be ignored and the object will be serialized more fastly.

Have you read my example in [this reply](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/7)?

In the example, I added custom key to store type information. It is used when deserializing.

```auto
    if isinsintance(obj, MyMapping):
        d = {" __type__": "MyMapping"}
        d.update(obj._data)
        return d

```

If default is not called, this example is broken.

---

<div class="post-metadata">

**Author:** ![Marco\_Sulla](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/marco_sulla/32/1451_2.png) [@Marco\_Sulla](https://discuss.python.org/u/Marco_Sulla)\
**Post date:** [December 14, 2019, 2:31pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/22 "2019-12-14T14:31:45Z")

</div>

> [@methane](#):
>
> If default is not called, this example is broken.

Excuse me, but adding a custom key to the map to signal how to deserialize the JSON seems not to me a good practice. This way if you want to deserialize it to a `dict`, you have to know that the JSON has that strange key, and remove it manually. If I see something in the code, I banter the coder 😃 If the code will broke because the company was so bold to update its Python version on its machines, well, I think they simply will remain to the previous Python version, or will fix the code.

Seriously, deserialization can’t know the type you want to deserialize. `json` gives you set of standard conversions, and this is really handy. But if you want to deserialize to a custom type, you have to tell to the deserializer the custom type, as any decent JSON library in any language do.

If you want to magically deserialize your data in a custom object, you wrong the data type. You have to use XML + XSD, or a typed JSON, or something similar.

So, IMHO the correct way to deserialize the JSON to `MyMap` is simply:

```python
def custom_deserialize(d):
    return MyMap(d)

```

or, simpler:

```python
d = json.loads(json_data)
mm = MyMap(d)

```

This is because, unluckily, `json` does not permit you to customize the conversion table. If this will be possible, not only you can directly convert JSON objects to `MyMap`, but also arrays to `tuple`s or `numpy.ndarray`s, and so on. Buy I suppose this is another problem.

---

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [December 15, 2019, 7:27am UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/23 "2019-12-15T07:27:03Z")

</div>

> [@Marco\_Sulla](#):
>
> but adding a custom key to the map to signal how to deserialize the JSON seems not to me a good practice.

Is it good practice or not is not a problem here.  
Removing the ability of customizing serialization of custom mapping types is backward incompatible change. It is the point.

> [@Marco\_Sulla](#):
>
> Seriously, deserialization can’t know the type you want to deserialize.

`json.loads` provides `object_hook` callback for it, as I demonstrated in the example code.

`object_hook` example in the official document also use the “bad practice”.

```auto
# https://docs.python.org/3/library/json.html
>>> import json
>>> def as_complex(dct):
... if ' __complex__' in dct:
... return complex(dct['real'], dct['imag'])
... return dct
...
>>> json.loads('{" __complex__": true, "real": 1, "imag": 2}',
... object_hook=as_complex)
(1+2j)

```

There are many customization in the world. The proposed change will break some of them.  
Backward compatibility is a strong reason to keep status quo.  
If you want to break backward compatibility, you need to show more strong and clear benefit.

---

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [December 15, 2019, 8:43am UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/24 "2019-12-15T08:43:25Z")

</div>

By the way, if you are thinking about frozendict, I’m +1 to support it by default when it is added in stdlib or built-in.  
There is no backward compatibility issue for the new type.

---

<div class="post-metadata">

**Author:** ![Marco\_Sulla](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/marco_sulla/32/1451_2.png) [@Marco\_Sulla](https://discuss.python.org/u/Marco_Sulla)\
**Post date:** [December 15, 2019, 3:35pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/25 "2019-12-15T15:35:56Z")

</div>

> [@methane](#):
>
> Removing the ability of customizing serialization of custom mapping types is backward incompatible change. It is the point.

I don’t think a developer should care about making incompatible changes of bad code, or no change will be ever made. I mean, there are people that uses “private” attributes of classes. If the language change and that “private” attribute changes or goes away, well, it’s your fault.

An alternative could be simply extending custom serialization also to builtin types. Indeed, I don’t know why I can’t be free to customize also default serializations. This will break nothing, since in past no builtin serialization was customized, simply because it was impossible.

> [@methane](#):
>
> if you are thinking about frozendict

Nope, but thank you 🙂

---

<div class="post-metadata">

**Author:** ![ericvsmith](https://avatars.discourse-cdn.com/v4/letter/e/34f0e0/32.png) [@ericvsmith](https://discuss.python.org/u/ericvsmith)\
**Post date:** [December 15, 2019, 7:09pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/26 "2019-12-15T19:09:48Z")

</div>

> [@Marco\_Sulla](#):
>
> I don’t think a developer should care about making incompatible changes of bad code, or no change will be ever made.

I realize you think that, and you are perfectly entitled to in your own libraries. But the Python devs are more conservative than you are.

> [@Marco\_Sulla](#):
>
> I mean, there are people that uses “private” attributes of classes. If the language change and that “private” attribute changes or goes away, well, it’s your fault.

This is an area where we’d be okay breaking existing code: if it uses an undocumented interface. But even then, we’d need to have a good reason to break such code.

---

<div class="post-metadata">

**Author:** ![Marco\_Sulla](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/marco_sulla/32/1451_2.png) [@Marco\_Sulla](https://discuss.python.org/u/Marco_Sulla)\
**Post date:** [December 15, 2019, 7:21pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/27 "2019-12-15T19:21:53Z")

</div>

@ericvsmith

> [@ericvsmith](#):
>
> But the Python devs are more conservative than you are.

Yes, Python 3 is the perfect example… 😃

> [@ericvsmith](#):
>
> we’d need to have a good reason to break such code.

My last proposal will break no old code. To recap:

1. let the `default` parameter of `json.dump` to manage also objects natively supported by `json`
2. add native support to `collections.abc` classes and subclasses, and to any object that seems to be a `supported-like` object, even with a slower, generic algorithm

“If it walks like a duck, it’s probably a duck” 🙂

---

<div class="post-metadata">

**Author:** ![nathanielmanistaatgoogle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nathanielmanistaatgoogle/32/2292_2.png) [@nathanielmanistaatgoogle](https://discuss.python.org/u/nathanielmanistaatgoogle)\
**Post date:** [June 6, 2020, 3:16pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/28 "2020-06-06T15:16:45Z")

</div>

To the best of my estimation [https://bugs.python.org/issue34858](https://bugs.python.org/issue34858) is the open [bugs.python.org](http://bugs.python.org) issue for the problem being discussed here.

---

<div class="post-metadata">

**Author:** ![merwok](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/merwok/32/29_2.png) [@merwok](https://discuss.python.org/u/merwok)\
**Post date:** [October 19, 2020, 10:25pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/29 "2020-10-19T22:25:36Z")

</div>

See also [https://bugs.python.org/issue30343](https://bugs.python.org/issue30343) about extensibility of JSONEncoder.

---

<div class="post-metadata">

**Author:** ![rickeylev](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rickeylev/32/1003_2.png) [@rickeylev](https://discuss.python.org/u/rickeylev)\
**Post date:** [April 29, 2022, 5:25pm UTC](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829/30 "2022-04-29T17:25:16Z")

</div>

I, too, believe json.dump should respect the ABCs. Part of the point of e.g. Mapping is precisely to allow people to _not_ have to use `dict`. A variety of other APIs in the stdlib respect them. Some special case the builtin types and use their internal APIs to gain performance, and then fall back to the more generic ABC apis. This is very reasonable behavior.

For reference:

- [MappingProxy objects should JSON serialize just like a dictionary · Issue #79039 · python/cpython · GitHub](https://github.com/python/cpython/issues/79039) and [Subclassed json.JSONEncoder does not respect default method for supported types · Issue #74528 · python/cpython · GitHub](https://github.com/python/cpython/issues/74528) were filed; some other discussion is there.
- A PR implementing this was rejected, saying it needed more discussion; [bpo-30343: New API for JSON encoder to override supported types by Xophmeister · Pull Request #1558 · python/cpython · GitHub](https://github.com/python/cpython/pull/1558)

[Previous page](https://discuss.python.org/t/json-does-not-support-mapping-and-mutablemapping/2829.md?page=1)
