Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add escape hatch for custom JSON serialization #1955

Merged
merged 6 commits into from
Mar 13, 2024

Conversation

vlindhol
Copy link
Contributor

@vlindhol vlindhol commented Mar 1, 2024

Summary

As reported in multiple issues (#1841, #1821, #1787, #1749), it was a surprising breaking change when some Python types became wrapped in a { "__type__": ..., "__value__": ...} envelope in 5.3.0 and subsequently deserialized back into the native types.

Using kombu.util.json.register_type() one could at least avoid e.g. datetime becoming deserialized into a datetime and keep it as a str as in <5.3.0, but it's currently impossible to get rid of the envelope itself.

This PR changes register_type() to accept marker=None, which signals that the JSON encoder should only transform the value using
the encoder arg, but should not stick the result in an envelope.

A side-effect of this is that the decoder thus becomes unnecessary to
specify (since there is no __type__ in the resulting JSON that would
activate it). If decoder is omitted, default to a simple identity function.

This way one can replicate the behavior of pre-5.3.0 fairly well by overriding the default-registered types as follows:

def _serialize_datelike(datetime_or_date):
    if not isinstance(datetime_or_date, datetime.datetime):
        datetime_or_date = datetime.datetime(
            datetime_or_date.year,
            datetime_or_date.month,
            datetime_or_date.day,
            0,
            0,
            0,
            0,
        )
    r = datetime_or_date.isoformat()
    if r.endswith("+00:00"):
        r = r[:-6] + "Z"
    return r


register_type(datetime.datetime, None, _serialize_datelike)
register_type(datetime.date, None, _serialize_datelike)
register_type(datetime.time, None, lambda o: o.isoformat())
register_type(uuid.UUID, None, lambda o: str(o))
register_type(Decimal, None, lambda o: str(o))

Tests

Added some unit tests around register_type(), which were completely missing before. Also tests the new functionality.

@Nusnus
Copy link
Member

Nusnus commented Mar 5, 2024

@vlindhol see lint errors please

Copy link
Member

@thedrow thedrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@Nusnus Nusnus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linting/pre-commit fails

Copy link
Member

@Nusnus Nusnus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linting/pre-commit fails

@vlindhol vlindhol requested a review from Nusnus March 13, 2024 09:10
Copy link
Member

@Nusnus Nusnus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlindhol
Copy link
Contributor Author

vlindhol commented Mar 13, 2024

https://github.com/celery/kombu/actions/runs/8262054534/job/22602777695#step:7:1

Sorry, didn't see that one! I thought CI looked green 😅 Manually ran all CI commands in ci.yaml now, and pushed fixes.

@vlindhol vlindhol requested a review from Nusnus March 13, 2024 10:33
@Nusnus Nusnus merged commit 25d02e6 into celery:main Mar 13, 2024
17 checks passed
@Nusnus
Copy link
Member

Nusnus commented Mar 13, 2024

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants