Current Firestore (1.30.0+) does not support updating an individual field with pojo as a value, thus the following code
data class Test(
val primitiveField: String,
val complexField: Test2
)
data class Test2(
val primitiveField1: String,
val primitiveField2: Int
)
val firestore = FirestoreOptions.getDefaultInstance().service
fun main() {
val test = Test("test", Test2("test", 123))
val docRef = firestore.collection("test").document("test")
docRef.set(test).get()
docRef.update("complexField", Test2("updated test", 456)).get()
}
yields to the following exception:
Exception in thread "main" com.google.cloud.firestore.FirestoreException: Cannot convert Test2(primitiveField1=updated test, primitiveField2=456) to Firestore Value
at com.google.cloud.firestore.FirestoreException.invalidState(FirestoreException.java:51)
at com.google.cloud.firestore.UserDataConverter.encodeValue(UserDataConverter.java:180)
at com.google.cloud.firestore.DocumentSnapshot.fromObject(DocumentSnapshot.java:89)
at com.google.cloud.firestore.UpdateBuilder.performUpdate(UpdateBuilder.java:513)
at com.google.cloud.firestore.UpdateBuilder.performUpdate(UpdateBuilder.java:502)
at com.google.cloud.firestore.UpdateBuilder.update(UpdateBuilder.java:389)
at com.google.cloud.firestore.DocumentReference.update(DocumentReference.java:261)
This is because UserDataConverter.encodeValue only accepts either primitive types or list or maps of primitive types (which get encoded recursively). However, I do not see any reason why pojos could not be accepted as valid field values. Further, CustomClassMapper.convertToPlainJavaTypes function used to convert pojos to maps could potentially be (re)used. In other words, the following workaround works (as long as you access the CustomClassMapper class through reflection as it is package-private) as expected:
docRef.update(
"complexField",
CustomClassMapper.convertToPlainJavaTypes(Test2("updated test", 456))
).get()
Related issues:
Current Firestore (1.30.0+) does not support updating an individual field with pojo as a value, thus the following code
yields to the following exception:
This is because UserDataConverter.encodeValue only accepts either primitive types or list or maps of primitive types (which get encoded recursively). However, I do not see any reason why pojos could not be accepted as valid field values. Further, CustomClassMapper.convertToPlainJavaTypes function used to convert pojos to maps could potentially be (re)used. In other words, the following workaround works (as long as you access the CustomClassMapper class through reflection as it is package-private) as expected:
Related issues: