I want to create an object that 'acts' like a string but when it's accessed, fires a function and returns that result.
The simple case for __str__ and __repr__ is easy enough; but I can't work out how to get json.dumps to treat it the same way;
import json, datetime
class DynamicString(str):
def __init__(self, genf):
self.generate = genf
def __repr__(self):
print("Called Repr")
return self.generate()
def __str__(self):
print("Called Str")
return self.generate()
dater=DynamicString(lambda: datetime.datetime.now().isoformat())
print(f"{dater!s}, {dater!r}, {dater!a}")
>>> Called Str
>>> Called Repr
>>> Called Repr
>>> 2019-05-01T13:52:12.588907, 2019-05-01T13:52:12.588933, 2019-05-01T13:52:12.588950
print(json.dumps(dater))
>>> "<function <lambda> at 0x10bb48730>"
It appears that however json.dumps is evaluating the object it's ignoring the custom dunder methods.
I can't use a custom JSONEncoder as this object is intended to be sent through modules I don't have access to modify. Any ideas?
UPDATE FOR CLARITY:
Expected output
json.dumps(dater)
>>> '"2019-05-01T16:43:21.956985"'
i.e. "Exactly as if it was just a normal string, but based on the current time"
strthat is not shown here? Or can you inherit from something else?json.dumps(str(dater))? Or build your own serialization method in case more complex behavior is expected?defaultwithindumpswon't work becausedefaultis only used for objects theJSONEncoderdoesn't already know how to handle (see table). In other words it won't be used becauseisinstance(dater, str)isTrue. It works in the answer you linked to because classDocisn't derived from something shown in the table.str, just act more-or-less like one. If that's true, there may be hope. However, you still haven't said what you would like or expect to get back from usingloads()on the JSON output produced.