Instead of traversing entire structure I hoped to use json.JSONEncoder, but I'm unable to get it to trigger on strings:
#!/usr/bin/env python3
import json
import datetime
class StringShortener(json.JSONEncoder):
def default(self, obj):
strl = 10
if not isinstance(obj, (int,float)) and len(str(obj))>strl:
return str(obj)[:strl] f"<<cut at {strl}>>"
return obj
mystruct = {
"dummy": "foobar just being more than 10char long",
"dt": datetime.datetime.now()
}
# only shortening the td object
print(json.dumps(mystruct, cls=StringShortener))
Gives:
{"dummy": "foobar just being more than 10char long", "dt": "2022-09-22<<cut at 10>>"}
But key 'dummy's value also match the stringShortener:
>>> obj = "foobar just being more than 10char long"
>>> bool(not isinstance(obj, (int,float)) and len(str(obj))>10)
True
>>> str(obj)[:10] f"<<cut at 10>>"
'foobar jus<<cut at 10>>'
How can this be fixed so str types also get shortened?
CodePudding user response:
Overriding the encode function should do it.
import json
import datetime
class StringShortener(json.JSONEncoder):
def default(self, obj):
strl = 10
if not isinstance(obj, (int,float)) and len(str(obj))>strl:
return str(obj)[:strl] f"<<cut at {strl}>>"
return obj
# just override the encode function in the same way as the default function
def encode(self, o):
strl = 10
# This is for extremely simple cases and benchmarks.s
if isinstance(o, str):
if self.ensure_ascii:
return o[:strl]
else:
return o
# cut the strings if they are too long
for key, value in o.items():
if isinstance(value, str):
o[key] = value[:strl] f"<<cut at {strl}>>"
# This doesn't pass the iterator directly to ''.join() because the
# exceptions aren't as detailed. The list call should be roughly
# equivalent to the PySequence_Fast that ''.join() would do.
chunks = self.iterencode(o, _one_shot=True)
if not isinstance(chunks, (list, tuple)):
chunks = list(chunks)
return ''.join(chunks)
mystruct = {
"dummy": "foobar just being more than 10char long",
"dt": datetime.datetime.now()
}
# shortening the td and dummy object
print(json.dumps(mystruct, cls=StringShortener))
giving:
{"dummy": "foobar jus<<cut at 10>>", "dt": "2022-09-23<<cut at 10>>"}