Skip to content

Firestore: support updating an individual field with pojo as a value #6711

@menulis

Description

@menulis

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:

Metadata

Metadata

Assignees

Labels

api: firestoreIssues related to the Firestore API.type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions