dash
dash copied to clipboard
[Feature Request] Add the ability to use a custom JSON encoder
Describe the Feature My use case is that I have a very simple custom type which stores a value in a standardised way ("aaabbbccc"), but displays the value in a prettier way ("aaa bbb ccc").
This is implemented simply like this:
class CustomType:
def __init__(self, value):
self.value = "".join(value.split())
def __str__(self):
return f"{self.value[:3]} {self.value[3:6]} {self.value[6:]}"
However, if I try and return this to the front end dashboard, I get:
component <X>
returned a value which is not JSON serializable.
In general, Dash properties can only be dash components, strings,
dictionaries, numbers, None, or lists of those.
Describe the solution you'd like
I would like to be able to override plotly.utils.PlotlyJSONEncoder
by doing something like this:
from plotly.utils import PlotlyJSONEncoder
from utils import CustomType
class CustomJSONEncoder(PlotlyJSONEncoder):
def default(self, obj):
if isinstance(obj, CustomType):
return str(obj)
return PlotlyJSONEncoder.default(self, obj)
app = Dash(__name__, json_encoder=CustomJSONEncoder)
Additional context As an example of how it could look, Flask gives the user the ability to override the default json encoder. Snippet.
An alternative method would be to implement a to_plotly_json
method within your class:
https://github.com/plotly/plotly.py/blob/7fcb95ce94652a48b744a06460d17c50a932c8a2/packages/python/plotly/_plotly_utils/utils.py#L99-L123
This works for classes that you have control over, doesn't work as well for classes that you don't have control over.
That's interesting - hadn't found that. I just had a quick look and I can't see it in the docs anywhere. That would certainly work for my use case, my only thought would be that it isn't very obvious at present. Coming from a Flask background, I expected to be able to provide my own custom encoder.
Hello! I have proposed a more flexible solution in another ticket: https://github.com/plotly/plotly.py/issues/2475
This seems to be needed to properly work with lazy_gettext
objects from Flask-Babel (for translation). See https://github.com/python-babel/flask-babel/issues/31
UPDATE: using a custom JSONEncoder wont be enough, since dash validates callback output in a strict way (_validate_value
). (which precludes the values from being LazyString
s)
Maybe a reasonable "protocol" would be to accept UserString objects and threat these the same way as any regular string in the validation and the serialization code? Then it would be easy to make the LazyString usable.