Skip to content
This repository was archived by the owner on Apr 10, 2023. It is now read-only.
This repository was archived by the owner on Apr 10, 2023. It is now read-only.

Add Support for Transparent and Alias Fields #124

@nickboucher

Description

@nickboucher

Compared to the comparable library in Rust, this package lacks support for Transparent and Alias fields. Adding support for these two features would increase interoperability with serialized data from projects written in Rust.

I would be happy to implement these myself and submit a PR, but at the moment my free time is rather limited. Here's an untested stab at what an implementation of these two features may look like (but certainly needs validation):

from serde import fields
from serde.exceptions import ValidationError

class Transparent(fields.Field):
    """Serialize and deserialize a newtype struct or a braced struct with one
       field exactly the same as if its one field were serialized and
       deserialized by itself."""

    def _deserialize_with(self, model, d):
        if len(d) != 1:
            raise ValidationError(
                'Transparent Fields {!r} must be only field in class'.format(
                    self._serde_name)
            )
        setattr(model, self._attr_name, self._deserialize(d[next(iter(d))]))
        return model, d

    def _serialize_with(self, model, d):
        return self._serialize(getattr(model, self._attr_name))


class Alias(fields.Field):
    """Allows the specification of an alternate deserialization field name for
       the contained field. Alias should not be the name of another field
       within the same model."""
    
    def __init__(self, aliases: str, *args, **kwargs):
        self.aliases = aliases
        super(Alias, self).__init__(*args, **kwargs)
    
    def _deserialize_with(self, model, d):
        for alias in self.aliases:
            if alias in self._model_cls._fields:
                raise ValidationError(
                    'Alias cannot contain existing field name {!r}'.format(
                        alias
                ))
        if self._attr_name in d:
            value = d[self._attr_name]
            setattr(model, self._attr_name, self._deserialize(value))
        else:
            for alias in self.aliases:
                if alias in d:
                    value = d[alias]
                    d[self._attr_name] = d.pop(alias)
                    setattr(model, self._attr_name, self._deserialize(value))
                    break
        return model, d

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions