-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Environment details
- Specify the API at the beginning of the title (for example, "BigQuery: ...")
General, Core, and Other are also allowed as types - OS type and version: any
- Java version: 8
- google-cloud-firestore version: 1.9.0 which comes with firebase-admin 6.9.0
Steps to reproduce
When doing an update of a list, using FieldValue.arrayUnion, and the value to add to that list is a custom object, it fails saying that it can't be converted to a firestore value, instead of saving it as a map in the database
Code example
class Transaction{
Integer x = 10;
//getters and setters
}
val accountRef = db.collection("accounts").document(accountId);
accountRef.update("transactions", FieldValue.arrayUnion(transaction));
Stack trace
com.google.cloud.firestore.FirestoreException: Cannot convert com.example.model.TransactionBean@5913f02e to Firestore Value
at com.google.cloud.firestore.FirestoreException.invalidState(FirestoreException.java:51)
at com.google.cloud.firestore.UserDataConverter.encodeValue(UserDataConverter.java:178)
at com.google.cloud.firestore.FieldValue$ArrayUnionFieldValue.toProto(FieldValue.java:157)
at com.google.cloud.firestore.DocumentTransform.fromFieldPathMap(DocumentTransform.java:52)
at com.google.cloud.firestore.UpdateBuilder.performUpdate(UpdateBuilder.java:530)
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)
Any additional information below
The solution I'm using is converting all objects into maps using reflection. It doesn't have any problem deserializing it back into an object.
The problem is in encodeValue, in the class UserDataConverter
It throws the exception after failing in every type. It should try to convert it to a map using the available attributes, as it does when deserializing back to an object.
I've made this converter in Scala to save this in firebase:
import java.util
import scala.collection.JavaConverters._
object ReflectionConverterForFirebase {
def getMap(caseClass: Product): util.Map[String, Any] = {
val values = caseClass.productIterator
caseClass.getClass.getDeclaredFields.map {
_.getName -> (values.next() match {
case p: Product if p.productArity > 0 => getMap(p)
case bigDecimal: BigDecimal => bigDecimal.toDouble
case x => x
})
}.toMap.asJava
}
}
Ideally, it should support receiving a mapper to json, or at least the json string too
Regards