New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nullable & optional/required marks #807
Comments
For what datatype? You can use |
For all datatypes. With Int - required & non-nullable |
I meant for what Java/Kotlin type. Sounds like you need to write your own to model those dimensions as j.u.Optional won't. |
I went with a custom import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
sealed class Omittable<out T> {
val provided get() = this !is Missing
abstract val value: T
object Missing : Omittable<Nothing>() {
// have the IDE raise an error if the user knows a type is missing but still tries to access a value
@Deprecated("Cannot access a missing value", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("TODO(\"value is missing\")"))
override val value: Nothing
get() = error("cannot access provided field")
}
class Provided<out T>(override val value: T) : Omittable<T>()
}
@UseExperimental(ExperimentalContracts::class)
fun <T> Omittable<T>.isMissing(): Boolean {
contract {
returns(true) implies (this@isMissing is Omittable.Missing)
}
return !provided
}
@UseExperimental(ExperimentalContracts::class)
fun <T> Omittable<T>.isProvided(): Boolean {
contract {
returns(true) implies (this@isProvided is Omittable.Provided<*>)
}
return provided
} and a custom accompanying adapter import com.squareup.moshi.*
import java.lang.reflect.Type
class OmittableAdapter<T>(private val valueAdapter: JsonAdapter<T>) : JsonAdapter<Omittable<T>>() {
@Suppress("UNCHECKED_CAST")
override fun fromJson(reader: JsonReader) = Omittable.Provided(valueAdapter.fromJson(reader) as T)
override fun toJson(writer: JsonWriter, value: Omittable<T>?) {
when (value) {
is Omittable.Missing -> writer.nullValue()
is Omittable.Provided -> valueAdapter.toJson(writer, value.value)
}
}
companion object Factory : JsonAdapter.Factory {
override fun create(type: Type, annotations: Set<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
return if (Types.getRawType(type) == Omittable::class.java && annotations.isEmpty()) {
val valueType = Types.collectionElementType(type, Omittable::class.java)
return OmittableAdapter(moshi.adapter<Any>(valueType).nullSafe())
} else {
null
}
}
}
}
// we don't actually use this, just defined to illustrate how it is registered to the builder
fun Moshi.Builder.addOmittableAdapter() {
add(OmittableAdapter)
} |
Then in my data class that I deserialize to, I default the omittable values to data class A(
val foo: Omittable<String> = Omittable.Missing,
val baz: Boolean
) |
No action to take on this. |
Can we represent that a field is non-nullable & optional?
this mean, or we send a data for the field, or just do not send the field in request, null is not allowed.
{"foo": "bar", "baz": true}
is allowed{"baz": true}
is allowed, because is optional{"foo": null, "baz": true}
is NOT allowed, because is non-nullableBasically
null
has the meaning of "this property existed before, and I want to nullify its value". If there's no value, or the value needs not change (for requests, for example), it just shouldn't be sent.This also is supported by OpenAPI and ReDoc.
The text was updated successfully, but these errors were encountered: