Open nerdoc opened 1 month ago
I am adding unittests for the TetraJSONEncoder/Decoders.
@samwillis, you wrote TetraJSONEncoder
that is a subclass of json.JSONEncoder
, but your docstring says it is based on DjangoJSONEncoder
. You were copying some of the code there, and extending the return value with a __type
hint within a dict, so you could decode it later easier. DjangoJSONEncoder
always returns a str, TetraJSONEncoder
a str or a dict[str, Any] - or everything the json.JSONEncoder supports (simple python objects).
Generally speaking, I tried to create a mermaid diagram - mainly to understand things better.
graph TD;
subgraph python[Plain Python objects]
int
str
wrongModel[Model]
end
subgraph special[Special objects]
Model
datetime
end
JSONDecoder --> wrongModel
wrongModel --> TypeError
int --> JSONEncoder
str --> JSONEncoder
JSONEncoder --> JSON-object
Model --> TetraJSONEncoder
datetime --> TetraJSONEncoder
TetraJSONEncoder --> JSON-object
subgraph serialized[JSON object]
JSON-object
end
JSON-object --> JSONDecoder
JSON-object --> TetraJSONDecoder
JSONDecoder --> str
JSONDecoder --> int
TetraJSONDecoder --> Model
TetraJSONDecoder --> datetime
I already added model support to it:
elif isinstance(obj, models.Model):
return {
"__type": f"model.{obj._meta.app_label}.{obj.__class__.__name__}",
"value": obj.pk,
}
After a few tests, I would want to merge two others that seem to be added in the meantime to Django:
elif isinstance(obj, datetime.timedelta):
return duration_iso_string(obj)
elif isinstance(obj, (decimal.Decimal, uuid.UUID, Promise)):
return str(obj)
The tests that I created showed that when I encode and decode a simple model, it works flawlessly.
But I have problems in a form that has a ForeignKey field despite the Js/Alpine data structure holding the correct index key of the model, it is not retrieved, and I can't see that the TetraJSONDecoder is ever called, when e.g. calling the "submit" method of the component.
I'm stuck here.
And on:
The TetraJSONDecoder
decodes the object when e.g. calling a method from the frontend/javascript: The TetraJSONDecoder.object_hook
it receives is a dict like this:
{'key': None, 'account_type': 1, 'country': 'AT', 'federal_state': '1', 'title': None, 'company_name': None,
'health_service_type': 'doc', 'medical_speciality': 'gp', 'phone_number': None, 'comment': None,
'identity_proof': None, 'profession_proof': None, 'first_name': None, 'last_name': None, 'email': None,
'terms_conditions': True}
this is a dict, and no special one with a __type
- just normal dict, which AFAIK will get fed into the component's data directly.
Maybe then my way of encoding the data is completely wrong, see above in https://github.com/tetra-framework/tetra/issues/64#issue-2329613568.
Because the TetraJSONEncoder.default()
never gets a model - but always a dict. And for simple str, int, dict objects, default()
is never called.
Maybe I am misunderstanding something. There are 2 classes in utils.py:
TetraJSONEncoder
andTetraJSONDecoder
. In theory, the purpose is clear, and I already extended both to handle models:But no matter how hard I debug tetra, I NEVER get the
TetraJSONEncoder.default()
method to get called. It is never, ever called. In https://github.com/tetra-framework/tetra/blob/3864e452fb8fb3a84fc662a686cd434b32fa5f07/tetra/utils.py#L81 TetraJSONEncoder is used, but internally, only.encode()
is called, and never.default()
.Is there anything I am missing?
@samwillis have you got a clue here? Maybe I did not fully understand the serialization workflow of Tetra.