1

I'm getting the following model from an API call through Retrofit:

data class User(
    @Expose val id: Int
    @Expose var username: String,
    @Expose var phoneNum: String?,
    @Expose var email: String?,
    @Expose var payments: List<PaymentMethod>
)

I need to add one extra attribute for reasons related to this SO answer.

The extra argument will be a data class PaymentsMethods:

data class PaymentsMethods(
    val paymentMethods: List<PaymentMethod>
)

How can I add the attribute value to User class when it is created?

Here is what I tried so far:

// add an attribute (with a default value) that won't be filled by the parser.
data class User(
    @Expose val id: Int
    @Expose var username: String,
    @Expose var phoneNum: String?,
    @Expose var email: String?,
    @Expose var payments: List<PaymentMethod>,
    @Expose var paymentsObject: PaymentMethods = PaymentMethods(payments)
)

and

// create variable and set the value on init
data class User(
    @Expose val id: Int
    @Expose var username: String,
    @Expose var phoneNum: String?,
    @Expose var email: String?,
    @Expose var payments: List<PaymentMethod>
){
init {
    var paymentsObject: PaymentMethods = PaymentMethods(payments)
    }
 }

None of them work. Any suggestion will be much appreciated.

kike
  • 4,255
  • 5
  • 23
  • 41
  • I would like to help but I have trouble reading your code. Aren't you supposed to use `@SerializedName` with the json key as value? `@Expose` only makes sense if you use `GsonBuilder#excludeFieldsWithoutExposeAnnotation` and I don't see you using it. Also, a class with a plural name doesn't make sense. If you use Room then you can create a TypeConverter to retrieve a list from Retrofit and directly store it. – Zun Nov 15 '18 at 13:53
  • Could you give a concrete example of what your json result looks like? (In text format, so not a POJO) – Zun Nov 15 '18 at 13:56
  • @ZUNJAE `@SerializedName` is only needed when the JSON attribute name differs from the POJO attribute name and for this case, I think we can ignore the `@Expose` annotation. – kike Nov 15 '18 at 14:05
  • @ZUNJAE and regarding the JSON, there is not need to add it. This question is about to create an extra attribute in the data class. – kike Nov 15 '18 at 14:07
  • Depending on how you compile your application (debug, release, proguard, dexguard etc.) these variable names will be changed so SerializedName is pretty important. – Zun Nov 15 '18 at 14:07
  • @ZUNJAE Regarding Room and TypeConverter usage. The reality is that TypeConverter is not working well deserialising lists (at least for me), so creating a wrapping object is the only solution I can see now. – kike Nov 15 '18 at 14:09

1 Answers1

0

I hope this is what you need:

data class User(
    @Expose val id: Int,
    @Expose var username: String,
    @Expose var phoneNum: String?,
    @Expose var email: String?
) {
    @Expose var payments: List<PaymentMethod> by Delegates.observable(listOf()) { 
        prop, oldValue, newValue ->
        paymentsObject = PaymentMethods(newValue)
    }
    lateinit var paymentsObject: PaymentMethods
}
Sergio
  • 27,326
  • 8
  • 128
  • 149
  • thanks for your answer. Unfortunately, it does not work either. Apparently, Retrofit does not follow the common object initialisation (uses reflection instead), so there is no way to add an extra attribute programmatically. – kike Nov 19 '18 at 10:21