Skip to content

Allow calling SerialDescriptor(name, original) when original.kind is PrimitiveKind #2547

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

Closed
lukellmann opened this issue Jan 16, 2024 · 5 comments
Assignees
Labels

Comments

@lukellmann
Copy link
Contributor

lukellmann commented Jan 16, 2024

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

This section of the Kotlin Serialization Guide recommends that delegating serializers should not reuse the descriptor of the serializer they are delegating to but instead wrap it with SerialDescriptor("OtherName", delegate.descriptor). This works fine if delegate.descriptor.kind is not PrimitiveKind. But for serializers that have a primitive descriptor, this will throw an exception.

This can cause problems if the delegated serializer just happens to have a primitive serial descriptor as an implementation detail.

An example for this is this serializer which delegates to JsonPrimitive.serializer(). However when writing this serializer, one shouldn't have to know what the serial descriptor for JsonPrimitive looks like if all that one wants to do is delegate serialization to JsonPrimitive.serializer(). Ideally you should always be able to call SerialDescriptor("OtherName", delegate.descriptor) to implement KSerializer.descriptor for a serializer that just delegates to delegate.

Describe the solution you'd like

Change the code for SerialDescriptor() to not throw when given a primitive descriptor. This could be done by simply delegating to PrimitiveSerialDescriptor():

public fun SerialDescriptor(serialName: String, original: SerialDescriptor): SerialDescriptor {
    require(serialName.isNotBlank()) { "..." }
    require(serialName != original.serialName) { "..." }

    val kind = original.kind
    return if (kind is PrimitiveKind) {
        PrimitiveSerialDescriptor(serialName, kind)
    } else {
        WrappedSerialDescriptor(serialName, original)
    }
}
@lukellmann
Copy link
Contributor Author

I'd be happy to implement this if it's accepted.

@sandwwraith
Copy link
Member

Yes, I think this is logical and will make writing delegating serializers easier. I'll be happy to receive your PR!

@lukellmann
Copy link
Contributor Author

I stumbled accross the situation where a primitive descriptor is nullable: this won't be copied over to the wrapped serializer by the code shown above. So it isn't as easy as I thought it would be.

@sandwwraith
Copy link
Member

You can use .nullable

public val SerialDescriptor.nullable: SerialDescriptor
to wrap it if original.isNullable

sandwwraith added a commit that referenced this issue Aug 7, 2024
and allow creating primitive descriptors via it as well.

This constructor function is a way to create a descriptor for your
custom serializer if it simply delegates to an existing one.
Since it fits its purpose and is unlikely to change in the future, we can promote it to stable API
alongside other descriptor builders.

Fixes #2547
qwwdfsad pushed a commit that referenced this issue Aug 26, 2024
and allow creating primitive descriptors via it as well.

This constructor function is a way to create a descriptor for your
custom serializer if it simply delegates to an existing one.
Since it fits its purpose and is unlikely to change in the future, we can promote it to stable API
alongside other descriptor builders.

Fixes #2547
sandwwraith added a commit that referenced this issue Aug 27, 2024
and allow creating primitive descriptors via it as well.

This constructor function is a way to create a descriptor for your
custom serializer if it simply delegates to an existing one.
Since it fits its purpose and is unlikely to change in the future, we can promote it to stable API
alongside other descriptor builders.

Fixes #2547
@sandwwraith sandwwraith self-assigned this Oct 3, 2024
sandwwraith added a commit that referenced this issue Oct 7, 2024
and allow creating primitive descriptors via it as well.

This constructor function is a way to create a descriptor for your
custom serializer if it simply delegates to an existing one.
Since it fits its purpose and is unlikely to change in the future, we can promote it to stable API
alongside other descriptor builders.

Fixes #2547
sandwwraith added a commit that referenced this issue Oct 9, 2024
and allow creating primitive descriptors via it as well.

This constructor function is a way to create a descriptor for your
custom serializer if it simply delegates to an existing one.
Since it fits its purpose and is unlikely to change in the future, we can promote it to stable API
alongside other descriptor builders.

Fixes #2547
@lukellmann
Copy link
Contributor Author

Thanks for implementing this @sandwwraith :)

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

2 participants