hello :wave: anyone have any tips and tricks on se...
# serialization
r
hello 👋 anyone have any tips and tricks on serialization/deserialization for a number (as in... could be int, double, etc.) Asking because the openapi spec is rather permissive on the definition of a number type, so it is perfectly valid for a spec writer to just put something like this
Copy code
"schemas": {
      "ComputeUnit": {
        "type": "number"
      },
      // ...
}
and leave it up to the consumer to figure out what kind of number it actually is. Is my best bet to write a custom serializer for
Number
(the kotlin stdlib class) that will grok the type at serialization time?
a
the OpenAPI spec has
number
for floats (so in Kotlin use
Float
or
Double
), and
integer
(so use
Int
or
Long
) And in principle if
minimum >= 0
you could consider unsigned integers (but I find they tend to be a bit annoying to use in code so regular signed integers are fine) https://swagger.io/docs/specification/data-models/data-types/#numbers
r
Ehhh this makes too big an assumption that people are being so strict with their specs 😉 problem with stuff like this is you have lots of JS and python ppl writing specs who are like “a number is a number right?” Also, technically, by the law of the spec, they are correct, as simply “type: number” means any number is valid.
a
yeah exactly, so you could use Float or Double
r
Well.. no… because it can be an int as well
a
if the value is
0
then that can be parsed to a Float - or am I missing something?
r
Perhaps, but the problem would be that in this case you are casting incorrectly. If it’s an int, you want to to stay as an int, if not, then double. That’s why I think that having the type be Number is more robust. If it can deserialize to an int, then do that, if not, double
a
okay, sure. It can be handy to keep the raw value. So what you could do is define the property as
val computeUnit: JsonElement
, and then in code use
computeUnit.toIntOrNull
You could define and use a custom serializer for that, if you wanted to encapsulate the logic. Probably what I’d do is create a wrapper class
Copy code
@Serializable
value class JsonNumber(private val value: JsonElement)
and then add some util functions/properties to convert it to an int/float
but you could create a custom serializer like
Copy code
object JsonNumberSerializer: KSerializer<Number> { ... }
and define a typealias so it’s easier to re-use it
Copy code
typealias JsonNumber = @Serializable(with = JsonNumberSerializer::class) Number
but from memory it’s quite tricky to use the raw Number type in code, and it ends up being more trouble than it’s worth