I have a Client
api. The json response looks like this:
{
"clientId": 1,
"createdAt": null,
"updatedAt": null,
"monthlyPaymentAmount": null,
"person": {
// Omitted data here
},
"paymentType": {
// Omitted data here
},
"deliveryInstructions": null,
"referralName": null,
"referralPhoneNumber": null,
"status": 0,
"startDate": null,
"eventDate": null,
}
So, using the Kotlin data class file from JSON to automatically create data classes from the json response, I've got with the following Client
data class which I've turned into a Room @Entity
with ForeignKeys
:
@Entity(
tableName = "client",
foreignKeys = [
ForeignKey(
entity = Account::class,
parentColumns = arrayOf("account_id"),
childColumns = arrayOf("account_id"),
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Person::class,
parentColumns = arrayOf("person_id", "account_id"),
childColumns = arrayOf("person_id", "account_id"),
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = PaymentType::class,
parentColumns = arrayOf("payment_type_id", "account_id"),
childColumns = arrayOf("payment_type_id", "account_id"),
),
],
indices = [
Index(value = arrayOf("client_id", "account_id"), unique = true)
]
)
data class Client(
@PrimaryKey
@ColumnInfo(name = "client_id") val clientId: Int,
@ColumnInfo(name = "delivery_notes") val deliveryInstructions: String,
@ColumnInfo(name = "event_date") val eventDate: Date,
@ColumnInfo(name = "monthly_payment_amount") val monthlyPaymentAmount: Float,
@ColumnInfo(name = "payment_type_id") val paymentType: Int,
@ColumnInfo(name = "person_id") val person: Int,
@ColumnInfo(name = "referral_name") val referralName: String,
@ColumnInfo(name = "start_date") val startDate: Date,
@ColumnInfo(name = "status") val status: Int,
@ColumnInfo(name = "updated_at") val updatedAt: Date,
@ColumnInfo(name = "synced_at") val syncedAt: Date,
)
There's also PaymentType
and Person
data classes which I'm omitting, but they do are Room @Entity
's as well.
The Room database needs to match the following database structure that has this CREATE TABLE
SQL statement:
CREATE TABLE client
(
client_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
updated_at TEXT NOT NULL,
synced_at TEXT NOT NULL,
person_id INTEGER NOT NULL,
payment_type_id INTEGER,
referral_name TEXT,
delivery_notes TEXT,
status INTEGER DEFAULT 1 NOT NULL,
monthly_payment_amount REAL,
start_date TEXT,
event_date TEXT,
CONSTRAINT client_fk1 FOREIGN KEY (account_id) REFERENCES account (account_id) ON DELETE CASCADE,
CONSTRAINT client_fk2 FOREIGN KEY (person_id, account_id) REFERENCES person (person_id, account_id) ON DELETE CASCADE,
CONSTRAINT client_fk4 FOREIGN KEY (payment_type_id, account_id) REFERENCES payment_type (payment_type_id, account_id),
CONSTRAINT client_pk PRIMARY KEY (client_id, account_id)
);
So, I've a Converters
class to deserialize the json response into Client
class as follows:
class Converters {
@TypeConverter
fun clientToJson(value: Client?): String? = Gson().toJson(value)
@TypeConverter
fun jsonToClient(value: String): Client = Gson().fromJson(value, Client::class.java)
@TypeConverter
fun paymentTypeToJson(value: PaymentType?): String? = Gson().toJson(value)
@TypeConverter
fun jsonToPaymentType(value: String): PaymentType =
Gson().fromJson(value, PaymentType::class.java)
@TypeConverter
fun objToJsonPerson(value: Person?): String? = Gson().toJson(value)
@TypeConverter
fun jsonToObjPerson(value: String): Person = Gson().fromJson(value, Person::class.java)
// Omitted list of converters here
}
I'm hesitant if the client
converter above does correctly creates PaymentType
and Person
objects automatically (mostly convinced that no). That's why I would like to know what's the proper way to deserialize a json response with nested objects into Room entities with Foreign Keys?
I'm most confused with Foreing Keys though. What will happen when the converter above tries to parse the "person": {}
object into the @ColumnInfo(name = "person_id")
which is of type Int
? Will it know that it is a ForeignKey
and will create a Person::class
automatically? How's the best/proper way to deserialize nested objects ensuring this relation between the tables is properly done?