-
-
Notifications
You must be signed in to change notification settings - Fork 113
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
NamedTuple to dictionary serialization #425
Comments
Howdy, I think it's a combination of nobody having asked for it and supporting libraries probably being able to handle named tuples natively. Most of the time, output from cattrs is directly piped to another library, like orjson or msgpack, and those probably support named tuples already (since they are tuples)? Although now that I think about it, the current approach is inadequate because it will not unstructure deeply. So yeah, agreed on it needing to be fixed. A little bit unsure on how to unstructure named tuples though, my first instinct would be to unstructure to lists (like ordinary tuples), not dicts. |
Ah thanks, good to know! IMO they are more like |
Hi, I'd like to contribute to the implementation of this. A "standard library" way to serialize a def is_namedtuple(x):
type_ = type(x)
bases = type_.__bases__
if len(bases) != 1 or bases[0] != tuple:
return False
fields = getattr(type_, '_fields', None)
if not isinstance(fields, tuple):
return False
return all(isinstance(f, str) for f in fields)
def unstructure(obj):
if isinstance(obj, dict):
return {key: unstructure(value) for key, value in obj.items()}
elif isinstance(obj, list):
return list(map(unstructure, obj))
elif is_namedtuple(obj):
return {key: unstructure(value) for key, value in obj._asdict().items()}
elif isinstance(obj, tuple):
return tuple(map(unstructure, obj))
else:
return obj I would suggest implementing the following way:
I would very happily put the work detailed in the list in a PR. Do let me know if you'd approach this any other way :) References: |
Interesting! A couple of points. I think we will want to unstructure namedtuples into tuples for backwards compatibility. I see your code unstructures them into dictionaries. This is also a useful feature, but it should be a strategy instead. Then anyone can apply this strategy to any converter and get the behavior. My first instinct would be to try to reuse the Then, write an adapter that can transform a NamedTuple class (not instance) into a list of attributes, like this. Then, in the strategy, override the hooks to generate the proper unstructuring functions. That's how I would go about it. Happy to provide guidance if you decide to try! |
Sounds good! How about I give it a try in a PR and we take it from there? |
Go for it! |
Howdy, I've just merged #491. This adds the namedtuples-as-tuples functionality to cattrs. I'll leave this issue open while other folks work on a strategy for namedtuples-as-dataclasses. |
this is fantastic! do you plan a new release to include namedtuples? |
Yep, finishing it up now. The only thing left is to rework the readme |
I know that I'm a pain in the ... but I'm looking forward to have namedtuples in cattrs. I'm happy to contribute with any changes needed, just let me know. |
Description
For my project, cachew, I've been trying to switch from using my custom serialization cold to some existing library.
After some evaluation, cattrs seems like the most promising since it works so well with python typing annotations.
One thing that stops me is that seems like it doesn't support
NamedTuple
? I feel like it should be treated just like a@dataclass
, but seems like cattrs just treats them as 'unknown' types and leaves intact.What I Did
This is kinda the minimal snippet that shows the issue:
The result is
So the dataclass is serialized just as expected, but the namedtuple is just left intact.
I searched in
cattrs
source code, and it seems likeNamedTuple
isn't mentioned at all -- so perhaps it was just forgotten rather than deliberately left out?I know I can implement a custom adapter, but feels like it makes sense to have them treated as dataclasses by default?
The text was updated successfully, but these errors were encountered: