Cattrs is currently only used in two places: Serialization for operator extra links, and for Lineage.

However cattrs is not a well maintained project and doesn't support many features that attrs itself does; in short, it's not worth the brain cycles to keep cattrs.
"""
        Workaround to serialize Param on older versions.
        In 2.2.0, Param attrs were assumed to be json-serializable and were not run through
        this class's ``serialize`` method.  So before running through ``deserialize``,
        we first verify that it's necessary to do.
        """
        class_name = param_dict["__class"]
        class_: type[Param] = import_string(class_name)
        attrs = ("default", "description", "schema")
        kwargs = {}
        def is_serialized(val):
            if isinstance(val, dict):
                return Encoding.TYPE in val
            if isinstance(val, list):
                return all(isinstance(item, dict) and Encoding.TYPE in item for item in val)
            return False
        for attr in attrs:
            if attr in param_dict:
                val = param_dict[attr]
                if is_serialized(val):
                    val = cls.deserialize(val)
                kwargs[attr] = val
        return class_(**kwargs)
    @classmethod
    def _serialize_params_dict(cls, params: ParamsDict | dict):