I want to convert a dictionary to a JSON string with boolean True
values translated to the number 1
and boolean False
values translated to the number 0
. I'm using a JSONEncoder
subclass, but it seems to ignore booleans ...
import json
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, bool):
return 1 if obj else 0
return super().default(obj)
data = { 'key-a' : 'a', 'key-true' : True, 'key-false' : False }
jsondata = json.dumps(data, cls=MyEncoder)
print(jsondata)
I want this to be the result:
{"key-true": 1, "key-a": "a", "key-false": 0}
However, this is what I get:
{"key-true": true, "key-a": "a", "key-false": false}
I know I can programatically modify the data before passing it to json.dumps
, but is there any way I can obtain my desired result via a JSONEncoder
subclass?
dumps() json. dumps() function converts a Python object into a json string. skipkeys: If skipkeys is True (default: False), then dict keys that are not of a basic type (str, int, float, bool, None) will be skipped instead of raising a TypeError.
json. dump() will preserve the ordder of your dictionary. Open the file in a text editor and you will see. It will preserve the order regardless of whether you send it an OrderedDict.
A fp is a file pointer used to write JSON formatted data into file. Python json module always produces string objects, not bytes objects, therefore, fp.
loads() takes in a string and returns a json object. json. dumps() takes in a json object and returns a string.
The default()
method of JSONEncoder
subclasses is called only when the encoder encounters an object it doesn't otherwise know how to serialize.
Unfortunately, the official documentation doesn't make this very clear. It's mentioned, but in the "keyword arguments" section for the class constructor, rather than in the documentation for the method:
If specified, default should be a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a
TypeError
. If not specified,TypeError
is raised.
This behaviour can easily be verified:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, bool):
print('got bool')
return 1 if obj else 0
if isinstance(obj, Foo):
print('got Foo')
return {'__Foo__': id(obj)}
print('got unknown')
return super().default(obj)
>>> class Foo: pass
...
>>> s = json.dumps({'a': False, 'b': True, 'c': Foo()}, cls=MyEncoder)
got Foo
>>> s
'{"a": false, "c": {"__Foo__": 140636444256856}, "b": true}'
JSONEncoder
isn't designed to easily allow overriding the serialization of objects it already knows how to serialize (which is a good thing: the whole point of standards like JSON is that they're, well, standard) … so if you really want to encode booleans as though they were integers, the easiest way to do so is probably to preprocess data as suggested in your question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With