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

Consider to implicitly apply Serializable annotation to the entire sealed hierarchy #2572

Open
arkivanov opened this issue Feb 17, 2024 · 4 comments
Labels

Comments

@arkivanov
Copy link

What is your use-case and why do you need this feature?

Parcelize allows the following code.

@Parcelize
sealed interface State : Parcelable {
    data object Loading : State
    data object Error : State
    data class Data(val data: String) : State
}

We are able to specify the annotation only once on the base State interface. With kotlinx-serialization we have to repeat the annotation for every implementing class, which is pretty verbose.

@Serializable
sealed interface State {
    @Serializable
    data object Loading : State

    @Serializable
    data object Error : State

    @Serializable
    data class Data(val data: String) : State
}

Describe the solution you'd like

It would be nice to be able to write as follows.

@Serializable
sealed interface State {
    data object Loading : State
    data object Error : State
    data class Data(val data: String) : State
}

Alternative API if changing the existing behaviour is undesirable.

@Serializable(inherited = true)
sealed interface State {
    data object Loading : State
    data object Error : State
    data class Data(val data: String) : State
}
@sandwwraith
Copy link
Member

Given that inheritors of the sealed interface can be defined anywhere in the project, and it is not mandatory for them to be in the same file, this would be hard from a technical standpoint: it would require the plugin to analyze every single class in the project and its superclasses, instead of focusing on @Serializable classes. It also brings questions for design: if my intention to have only some of the inheritors serializable, how can I opt-out?

To sum up, we cannot change the behavior of the existing @Serializable annotation, as it would not be backward-compatible. It is possible to implement additional annotation though, that would cover the exact use case you've presented here. E.g. @SerializableSubclasses for nested classes or classes in the same file.

@arkivanov
Copy link
Author

@SerializableSubclasses sounds good as well. What about adding an optional argument to @Serializable? E.g. inherited: Boolean with default value false to keep the current behaviour as default, and make the new feature opt-in.

@sandwwraith
Copy link
Member

@Serializable also can be applied to the properties to specify custom serializer, so inherited parameter there would look illogical.

@pdvrieze
Copy link
Contributor

pdvrieze commented Feb 29, 2024

In some way the serializable annotation adds an expectation to the type (in that a valid expectation could be that all its subclasses/implementations are also serializable).

On the other hand there may be implementations that can not be serializable (and the parent must be to support serializability of the sibling) – This is more of an "abstract serializability" (often with abstract base types).

Given this dichotomy it seems that either a different annotation (or parameter) would work (as well as maybe have the plugin generate warnings on missing child serializers).

The biggest challenge I see is the change of annotations being an API change

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

No branches or pull requests

3 participants