Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Firestore: Objects inside list are not supported on serialization #6039

@leoxs22

Description

@leoxs22

Environment details

  1. Specify the API at the beginning of the title (for example, "BigQuery: ...")
    General, Core, and Other are also allowed as types
  2. OS type and version: any
  3. Java version: 8
  4. 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

https://github.com/googleapis/google-cloud-java/blob/master/google-cloud-clients/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UserDataConverter.java#L97

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

Metadata

Metadata

Assignees

Labels

api: firestoreIssues related to the Firestore API.type: questionRequest for information or clarification. Not an issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions