I need to parse Firebase DataSnapshot
(a JSON object) into a data class, whose properties include enum and list. So I prefer parsing it manually by passing the DataSnapshot
into a secondary constructor. However, I want the construction to fail if some fields are missing in the DataSnapshot
. In Swift, it has failable initializer that returns null so I know it has failed. How to do that in Kotlin?
The following is my attempt, but I assume you can't just return from a constructor, right?
data class Unit(val name: String, val type: UnitType, val components: List<Component>) {
constructor(snapshot: DataSnapshot) {
name = snapshot.child("name").value as? String ?: return
val typeString = snapshot.child("type").value as? String ?: return
type = UnitType.values().firstOrNull { it.abbrv == typeString } ?: return
...
}
}
Kotlin initThe code inside the init block is the first to be executed when the class is instantiated. The init block is run every time the class is instantiated, with any kind of constructor as we shall see next. Multiple initializer blocks can be written in a class.
Constructors The primary constructor is a part of the class header, and it goes after the class name and optional type parameters. The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks prefixed with the init keyword.
?: takes the right-hand value if the left-hand value is null (the elvis operator). :: creates a member reference or a class reference.
There is the require
function which was designed for this purpose:
// ...
init {
require(foo == "bar") {
"$foo should be equal to 'bar'"
}
}
There is also requireNotNull
, check
, error
and some others. These are called Preconditions in Kotlin. There is no magic here, they are just some helper functions. You can check the actual source here, it is very useful. There is a related blog post about the topic here.
No, you can't just return from a constructor - it doesn't make much sense conceptually - but since I'm fairly naive on Kotlin syntax, I'll answer to a more broad paradigm here.
Your data class is not responsible for error checking or error handling. It is only responsible for storing data. Therefore, you should rely on a factory pattern to parse the result of a DataSnapshot
and conditionally instantiate a new instance of Unit
if and only if no fields are missing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With