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

Enable variable serialization with parameters to "to_dict" #110

Closed
gshank opened this issue May 17, 2023 · 6 comments · Fixed by #117
Closed

Enable variable serialization with parameters to "to_dict" #110

gshank opened this issue May 17, 2023 · 6 comments · Fixed by #117
Assignees
Labels
enhancement New feature or request

Comments

@gshank
Copy link
Contributor

gshank commented May 17, 2023

Is your feature request related to a problem? Please describe.
We serialize in a number of different places for different purposes. One purpose is to enable reloading generated objects, the other is to write out json artifacts for user consumption. We'd like to be able to omit some fields in the json artifacts that are included in the serialized objects for reloading. If it was a single object it would be easy to use a custom method, but our structures are pretty deeply nested in some cases and it's difficult to pass along parameters.

Describe the solution you'd like
It would be nice to be able to provide a parameter to to_dict, such as: obj.to_dict(option="artifact"), that we could pass up the to_dict() chain and use for removing some dictionary keys from the serialization with particular options.

Describe alternatives you've considered
A "to_artifact" method that calls to_dict falls apart when we need to go through nested objects. Setting an environment variable wouldn't work because of threading and multiple executions at the same time.

I've looked over the current list of features and don't see a way of doing what I want, but would be glad to find out there is some way to do this.

@Fatal1ty
Copy link
Owner

Hi @gshank

Correct me if I missed something. Is it what you're looking for?

class BaseModel(DataClassDictMixin):
    class Config(BaseConfig):
        code_generation_options = [ADD_SERIALIZATION_CONTEXT]


@dataclass
class Bar(BaseModel):
    baz: int

    def __pre_serialize__(self, context: Optional[Dict] = None):
        return self

    def __post_serialize__(self, d: Dict, context: Optional[Dict] = None):
        if context and context.get("omit_baz"):
            d.pop("baz")
        return d


@dataclass
class Foo(BaseModel):
    bar: Bar
    baz: int

    def __pre_serialize__(self, context: Optional[Dict] = None):
        return self

    def __post_serialize__(self, d: Dict, context: Optional[Dict] = None):
        if context and context.get("omit_baz"):
            d.pop("baz")
        return d


foo = Foo(bar=Bar(baz=1), baz=2)
assert foo.to_dict() == {"bar": {"baz": 1}, "baz": 2}
assert foo.to_dict(context={"omit_baz": True}) == {"bar": {}}

We can create a new option like ADD_SERIALIZATION_CONTEXT and use it for passing optional context from to_* methods to serialization hooks and down to to_* methods of nested dataclasses if they also have this option enabled.

@gshank
Copy link
Contributor Author

gshank commented May 17, 2023

That looks like just what I want! Wonderful :)

@Fatal1ty Fatal1ty added the enhancement New feature or request label May 17, 2023
@Fatal1ty
Copy link
Owner

Good, I don't see anything complicated here, so I'll do my best to include it in the upcoming release along with discriminated unions I'm currently working on.

@gshank
Copy link
Contributor Author

gshank commented May 17, 2023

The discriminated unions will be useful for us too, since we have custom code to check the value of a particular field in order to choose the right class.

@Fatal1ty
Copy link
Owner

@gshank

I did what you asked. Do you have any chance to do a final check of the new option before the release?
You can install it from this branch:

pip install git+https://github.com/Fatal1ty/mashumaro.git@serialization-context

@Fatal1ty
Copy link
Owner

Ok, I'm putting together a release. If something pops up, we will fix it in the next version.

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

Successfully merging a pull request may close this issue.

2 participants