3

I have the following data class in Kotlin:

import com.google.gson.annotations.SerializedName

data class RouteGroup(
    @SerializedName("name") var name: String,
    @SerializedName("id") var id: Int
)

Sometimes I need to create an object with both fields, sometimes with only one of them.

How can I do this?

EDIT

This is not the duplicate of this question: Can Kotlin data class have more than one constructor? That question shows how to set a default value for a field. But in my case, I don't need to serialize the field with the default value. I want a field to be serialized only when I explicitly assign a value to it.

Vitali Plagov
  • 722
  • 1
  • 12
  • 31
  • https://proandroiddev.com/creating-multiple-constructors-for-data-classes-in-kotlin-32ad27e58cac https://stackoverflow.com/questions/44391468/can-kotlin-data-class-have-more-than-one-constructor – While True Dec 19 '18 at 14:23

2 Answers2

4

it is easy you have to use the nullable operator

import com.google.gson.annotations.SerializedName

data class RouteGroup @JvmOverloads constructor(
    @SerializedName("name") var name: String? = null,
    @SerializedName("id") var id: Int? = null
)
gmetax
  • 3,853
  • 2
  • 31
  • 45
  • Ok, so when I initialize the object I do it like: `new RouteGroup("my name", null)` or add a new constructor for the `name` field only and set `null` as a default value for an `id` field? It works like this. But I'm just afraid that if I would have a bigger DTO, then I would need to create constructors for every possible combination of passed fields. – Vitali Plagov Dec 19 '18 at 15:14
  • you can set them as default with null so you will not need another constructor – gmetax Dec 19 '18 at 15:15
  • Set default with null like this? `data class RouteGroup (@SerializedName("name") var name: String? = null, @SerializedName("id") var id: Int? = null)` If I do so, then I get a compilation error when initializing an object with `new RouteGroup("my name")`. The compilation error is: _Cannot resolve constructor 'RouteGroup(java.lang.String)'_ – Vitali Plagov Dec 19 '18 at 15:19
  • not even like that `new RouteGroup(name="my name")` – gmetax Dec 19 '18 at 15:21
  • It doesn't compile for me with this declaration as well. I'm creating this object in a Java class. Can it be the case? – Vitali Plagov Dec 19 '18 at 15:24
  • use the annotation @JvmOverloads – gmetax Dec 19 '18 at 15:25
1

You may need something like this:

sealed class RouteGroup

data class RouteGroupWithName(
    @SerializedName("name") var name: String
) : RouteGroup()

data class RouteGroupWithId(
    @SerializedName("id") var id: Int
) : RouteGroup()

data class RouteGroupWithNameAndId(
    @SerializedName("name") var name: String,
    @SerializedName("id") var id: Int
) : RouteGroup()

EDIT 1:

Or you can use nullable fields and named parameters like this:

data class RouteGroup(
    @SerializedName("name") var name: String? = null,
    @SerializedName("id") var id: Int? = null
)

val routeGroupWithName = RouteGroup(name = "example")
val routeGroupWithId = RouteGroup(id = 2)
val routeGroupWithNameAndId = RouteGroup(id = 2, name = "example")
TheKarlo95
  • 1,144
  • 9
  • 17
  • That doesn't look like a good solution. Even with a small number of fields, the number of possible combinations for a data class grows very fast. – Vitali Plagov Dec 19 '18 at 15:10
  • Why don't you just use nullable values. – TheKarlo95 Dec 19 '18 at 15:22
  • 1
    In Kotlin, classes are cheap, for generic data classes it's okay to inherit, but you can't without making the class open as in Kotlin by default everything is final. – Sharan Dec 19 '18 at 15:33