Skip to content

Improve documentation for buildClassSerialDescriptor #1434

@cris-null

Description

@cris-null

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

I'm trying to build a custom KSerializer for a class that has a list property:

@Serializable(with = ListingSerializer::class)
data class Listing(
    val after: String?,
    val before: String?,
    val posts: List<Post>
)

object ListingSerializer: KSerializer<Listing> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Listing") {
        element<String>("after")
        element<String>("before")
       // what to put in here ??
    }

    override fun serialize(encoder: Encoder, value: Listing) {  ...  }
    override fun deserialize(decoder: Decoder): Listing {  ...  }
}

The hand-written composite serializer section for the serializers guide says to use buildClassSerialDescriptor. However, it does not say that to use when using collections. The guide for json also has a few snippets where buildClassSerialDescriptor is used, but not for collections.

Checking the documentation for buildClassSerialDescriptor itself, I'm quite confused because it doesn't show buildClassSerialDescriptor but instead SerialDescriptor. Am I supposed to use SerialDescriptor instead? That's not what it's in the guide, so I'm a bit confused.

Inside it are these three lines:

    element<Long>("_longField") // longField is named as _longField
    element("stringField", listDescriptor<String>())
    element("nullableInt", descriptor<Int>().nullable)

This seems similar to what the guide says about buildClassSerialDescriptor, but calling them inside it does not work for listDescriptor or descriptor<Int>().nullable.

In the documentation for buildClassSerialDescriptor, there also an example for generic classes. In it, there's listSerialDescriptor which is what I used for my case.

override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Listing") {
    element<String>("after")
    element<String>("before")

    // is this better?
    element("things", listSerialDescriptor(Post.serializer().descriptor))
    // or is this better?
    element("things", listSerialDescriptor<Post>())
}

My code works great! Although it says it's "experimental" so I'm not sure if it's the recommended way to do it.

Describe the solution you'd like

I think it would be pretty cool if the guide had an example for a descriptor using a collection, or if the documentation for buildClassSerialDescriptor looked a bit more like how it's used in the guide (and with a collection example).

Environment

  • Kotlin version: 1.4.32
  • Library version: 1.4.32
  • Kotlin platforms: JVM
  • Gradle version: 6.7
  • IDE version: 2021.1
  • Other relevant context: Java 11, Linux 5.10

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions