Change json.dumps behaviour : customize serialization
Question:
Imagine, I’ve got a dict {"a": "hello", "b": b"list"}
- ‘a’ is a string
- ‘b’ is a byte string
I would like to serialize the dict into the "json"(*) string –> ‘{"a": "hello", "b": list}’
(*) : not really json compliant
For that, i’ve written that method, it works ….
def stringify(obj):
def my(obj):
if isinstance(obj,bytes):
return "<:<:%s:>:>" % obj.decode()
return json.dumps(obj, default=my).replace('"<:<:',"").replace(':>:>"',"")
(the "<:<:" & ":>:>" are just here, to be replaced, post json serailisation, to obtain the desired result)
It’s a little be hacky, using string substitution to obtain the result … it works 😉
I ask myself, and you, if it can be done in a better/python way …
Do you have any idea ?
Answers:
In order to achieve your desired output, i.e. '{"a": "hello", "b": list}'
you will need to do some ugly, but fair cosmetic changes, such as reconstructing the dictionary by yourself. As the plain old dictionary {"a": "hello", "b": list}
makes no sense as a python variable (well, this specific example does, only because we’re using the built-in list
, but if it was "mymethod" or anything else – it wouldn’t)
def stringify(input_dict: dict):
for k, v in input_dict.items():
if isinstance(v, bytes):
input_dict[k] = v.decode()
else:
input_dict[k] = f'"{v}"'
return '{' + ', '.join([f'{k}: {v}' for k, v in input_dict.items()]) + '}'
We can see that here we are reconstructing literally a dictionary using ASCII characters, not that bad, not that intuitive but nontheless works as intended.
Your solution does not work, or will not work if one of the values in the dictionary has this special set of characters <:<:
.
Making this code:
d = {"a": "hello", "b": b"list"}
serialized_dict = stringify(d)
print(serialized_dict)
Output:
{a: "hello", b: list}
Which is of type str
, NOT a valid JSON one.
Imagine, I’ve got a dict {"a": "hello", "b": b"list"}
- ‘a’ is a string
- ‘b’ is a byte string
I would like to serialize the dict into the "json"(*) string –> ‘{"a": "hello", "b": list}’
(*) : not really json compliant
For that, i’ve written that method, it works ….
def stringify(obj):
def my(obj):
if isinstance(obj,bytes):
return "<:<:%s:>:>" % obj.decode()
return json.dumps(obj, default=my).replace('"<:<:',"").replace(':>:>"',"")
(the "<:<:" & ":>:>" are just here, to be replaced, post json serailisation, to obtain the desired result)
It’s a little be hacky, using string substitution to obtain the result … it works 😉
I ask myself, and you, if it can be done in a better/python way …
Do you have any idea ?
In order to achieve your desired output, i.e. '{"a": "hello", "b": list}'
you will need to do some ugly, but fair cosmetic changes, such as reconstructing the dictionary by yourself. As the plain old dictionary {"a": "hello", "b": list}
makes no sense as a python variable (well, this specific example does, only because we’re using the built-in list
, but if it was "mymethod" or anything else – it wouldn’t)
def stringify(input_dict: dict):
for k, v in input_dict.items():
if isinstance(v, bytes):
input_dict[k] = v.decode()
else:
input_dict[k] = f'"{v}"'
return '{' + ', '.join([f'{k}: {v}' for k, v in input_dict.items()]) + '}'
We can see that here we are reconstructing literally a dictionary using ASCII characters, not that bad, not that intuitive but nontheless works as intended.
Your solution does not work, or will not work if one of the values in the dictionary has this special set of characters <:<:
.
Making this code:
d = {"a": "hello", "b": b"list"}
serialized_dict = stringify(d)
print(serialized_dict)
Output:
{a: "hello", b: list}
Which is of type str
, NOT a valid JSON one.