Moshi: default value in kotlin data class not work when server send null for that value

Created on 28 Nov 2018  路  14Comments  路  Source: square/moshi

json:

{
      "percentChange": null,
      "change": "-2500.00",
      "value": "130000",
      "name": null
}

data class:

@JsonClass(generateAdapter = true)
data class Reference(

    val name: String? = "-",
    val value: Double,
    val change: Double,
    val percentChange: Double? = -10.0
)

but data for name and percentChange is null that should "-" for name and "-10.0" for percentChange. if server not send name and percentChange, default value work, but if send that null default value not work!
I use converter-moshi:2.4.0 and retrofit:2.4.0

Most helpful comment

@NightlyNexus
Well, this is kind of good for a small module, but imagine something like 50 field modules with the server can send nulls for most of them (30 for example). Then it can get really ugly really fast with one backing up field (with the default value) for each nullable field, right?

As I was asking @swankjesse, I really think this should be approached from the parser "Moshi" side, not the models itself, the models already defined their defaults as per the language "Kotlin" specs.

Now I understand that it was a design decision and that's ok, I was wondering if you can point me how to extend the auto-gen adapter so I can have an auto-gen adapter like the one you guys create but with this added functionality. :)

All 14 comments

Yeah, that's working as designed. Defaults and nullability are independent concerns.

Hello @swankjesse, are you guys considering this to be changed in the [near] future?

If not, I want to have a shot of building a custom adapter that covers this issue (that is also generated as the ones you guys create), can you point me how/where to start? :)

I'd really appreciate it. :)

Stripping nulls is a good strategy.

@swankjesse I'm sorry, but I don't fully understand your replay. Can you elaborate more? :)

If you by "Stripping nulls" you mean remove them from the response itself, then that won't work if you don't have access to the service "backend" side if I understand you correctly.

Download the JSON, remove the nulls, convert to your models?

@swankjesse
Well yes, but as far as I understand, when you're using Moshi with retrofit this operation (Download Json -> convert to Model) will happen before you actually get the response. Unless we intercept the response on the OkHttp client level, which actually seems like a bit wired to do that on the client level, am I missing something here?

I've always thought that this should be done as part form the parser level.

how about this?

@JsonClass(generateAdapter = true)
class Reference(
  name: String? = "-",
  val value: Double,
  val change: Double,
  percentChange: Double? = -10.0) {
  val name: String = name ?: "-"
  val percentChange: Double = percentChange ?: -10.0
}

@NightlyNexus
Well, this is kind of good for a small module, but imagine something like 50 field modules with the server can send nulls for most of them (30 for example). Then it can get really ugly really fast with one backing up field (with the default value) for each nullable field, right?

As I was asking @swankjesse, I really think this should be approached from the parser "Moshi" side, not the models itself, the models already defined their defaults as per the language "Kotlin" specs.

Now I understand that it was a design decision and that's ok, I was wondering if you can point me how to extend the auto-gen adapter so I can have an auto-gen adapter like the one you guys create but with this added functionality. :)

how about this?

@JsonClass(generateAdapter = true)
class Reference(
  name: String? = "-",
  val value: Double,
  val change: Double,
  percentChange: Double? = -10.0) {
  val name: String = name ?: "-"
  val percentChange: Double = percentChange ?: -10.0
}

This doesn't work for data classes

@AbdAllahAbdElFattah13 you can fetch the generated adapter indirectly via Moshi#adapter or Moshi#nextAdapter API in your own JsonAdapter.Factory implementation and just use delegation. In the next release we'll support custom generators so you can generate your own if you want, but otherwise we have no plans to support custom extensions to the adapters that Moshi generates itself

@mgray88 please file a separate issue with more details if you want to pursue that, unfortunately that's not enough information for us to help!

Closing this out for now, but happy to continue the discussion if needed

how about this?

@JsonClass(generateAdapter = true)
class Reference(
  name: String? = "-",
  val value: Double,
  val change: Double,
  percentChange: Double? = -10.0) {
  val name: String = name ?: "-"
  val percentChange: Double = percentChange ?: -10.0
}

This doesn't work for data classes

Also works for data class, but more ugly.

@JsonClass(generateAdapter = true)
data class Reference(
        @Json(name = "name") private val _name: String? = "-",
        val value: Double,
        val change: Double,
        @Json(name = "percentChange") private val _percentChange: Double? = -10.0
) {
    val name: String = _name ?: "-"
    val percentChange: Double = _percentChange ?: -10.0
}

Check my answer here and see if it will help you

Was this page helpful?
0 / 5 - 0 ratings