{
"breviario": {
"metaLiturgia": {
"fecha" : "Martes 5 de febrero del 2019",
"tiempo" : "PROPIO DE LOS SANTOS",
"semana" : "",
"mensaje": "",
"salterio": "",
"color":0,
"meta": ""
},
"santo": {
"nombre": "Santa Águeda, virgen y mártir",
"vida": "Padeció el martirio en Catania (Sicilia), probablemente en la persecución de Decio. Desde la antigüedad su culto se extendió por toda la Iglesia y su nombre fue introducido en el Canon romano."
},
"oficio": {
"himno": {
"texto": "Testigos de amor~de Cristo Señor,~mártires santos.§Rosales en flor~de Cristo el olor,~mártires santos.§Palabras en luz~de Cristo Jesús,~mártires santos.§Corona inmortal~del Cristo total,~mártires santos. Amén."
},
"salmodia": {
...
Oficio
:public class Oficio {
private Invitatorio invitatorio;
private Himno himno;
private Salmodia salmodia;
private String oracion;
private String responsorio;
private OficioLecturas oficioLecturas;
public Oficio () {}
public Himno getHimno() {
return himno;
}
public void setHimno(Himno himno) {
this.himno = himno;
}
// ...
}
Himno
:public class Himno {
private String texto;
public Himno () {}
public Spanned getTexto() {
Spanned str = Utils.fromHtml(Utils.getFormato(texto));
return str;
}
public void setTexto(String texto) {
this.texto = texto;
}
//...
}
DocumentReference docRef = db.collection("liturgia").document("breviario")
.collection("oficio").document("20190204");
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Oficio oficio = documentSnapshot.toObject(Oficio.class);
Himno himno=oficio.getHimno();
Log.d(TAG,oficio.getOracion().toString()); //Correct
}
});
I can't read the property himno
as the custom class 'Himno'. When I try, I get a 'RuntimeException' even if I comment the line: Himno himno=oficio.getHimno();
. I can however get the property oracion
into the corresponding variable.
E/AndroidRuntime: FATAL EXCEPTION: main Process: org.my.app, PID: 10532 java.lang.RuntimeException: Could not deserialize object. Can't convert object of type com.google.firebase.firestore.DocumentReference to type org.my.app.model.Himno (found in field 'himno') at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(com.google.firebase:firebase-firestore@@17.1.2:524) at com.google.firebase.firestore.util.CustomClassMapper.convertBean(com.google.firebase:firebase-firestore@@17.1.2:505) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-firestore@@17.1.2:242) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(com.google.firebase:firebase-firestore@@17.1.2:180) at com.google.firebase.firestore.util.CustomClassMapper.access$200(com.google.firebase:firebase-firestore@@17.1.2:53) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@17.1.2:700) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@17.1.2:674) at com.google.firebase.firestore.util.CustomClassMapper.convertBean(com.google.firebase:firebase-firestore@@17.1.2:503) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-firestore@@17.1.2:242) at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-firestore@@17.1.2:97) at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.2:203) at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.2:183)
You are getting the following error:
Can't convert object of type com.google.firebase.firestore.DocumentReference to type org.my.app.model.Himno (found in field 'himno')
Because you are trying to convert a DocumentReference
object to a Himno
object. There is no way in Java to achieve this since there is no inheritance relationship between them.
The document that you are trying to get from the following location:
db.collection("liturgia").document("breviario").collection("oficio").document("20190204");
Is of type Oficio
, so the following line of code:
Oficio oficio = documentSnapshot.toObject(Oficio.class);
Will work perfectly fine. The problem is when you are trying to get the Himno
object which is nested under your Oficio
class like this:
Himno himno=oficio.getHimno();
And this will not work in the way you do since your himno
property inside the document holds a value which is of type DocumentReference
and not of type Himno
.
See, the himno
property has a reference. If you want to get that document reference, simply use:
DocumentReference documentReference = documentSnapshot.getDocumentReference("himno");
If you want to use:
Himno himno=oficio.getHimno();
Then change the himno
property to be of type Himno
and not DocumentReference
.
Another issue in your code, as also @Anees pointed out in his aswer is that the getTexto()
method should return a String
and not a Spanned
object because this the way in which is stored in the database.
See, the texto
property holds a String and not a Spanned
. But this is not the reason why your error occurs.
Please also note, that the following sentence:
Custom classes in Firestore must contain
Is incorrect! There isn't a must for the public no-argument constructor nor for the public getters.
So you class might simply look like this:
public class Oficio {
public Invitatorio invitatorio;
public Himno himno;
public Salmodia salmodia;
public String oracion;
public String responsorio;
public OficioLecturas oficioLecturas;
}
Without any constructors, setters or getters at all. More informations here.
Edit:
According to your comment:
I changet the type of getTexto() from Spanned to String, but is not working.
Changing only the return type of your getTexto()
method from Spanned
to String
will not help you solve the main error.
I don't understand how i can change the himno property to be of type Himno and not DocumentReference.
You haven't shared the way you are adding the data to the database but it's actually very simple. First, remove that himno
property from those documents. Then, when you are adding a new document, instead of adding a DocumentReference
, add an object of type Himno
, as I also see that you have declared in your Oficio
class. This also means, that when you'll use the following line of code:
Himno himno=oficio.getHimno();
An object of type Himno
will be returned and not a DocumentReference
. This is because it is stored accordingly to its data type.
In RealTimeDatabase is possible to take only one object (Oficio par example) and from this object i can get references to another nested object (Himno par example).
This can be also done in Cloud Firestore but you need to get the data according to the data type of your property it exists in the database. If your property is of type DocumentReference
, you cannot get it as a type Himno
, unless you add it like so.
See the section named "Custom objects" in the docs
Yes, I see. That's why I told you to get the data according to the data type it is stored. So if you have the data stored as a DocumentReference
, get it according to it. If you want to get it as a Himno
, store it as a Himno
in the first place and then get it accordingly.
Edit2:
Are you telling me that in can create a field of type Himno in Firestore?
Yes, you can do it. How did you add that reference in the database? In the same way you added that reference add the Himno
object.
I don't understand how i can achieve this.
When you are adding data to the database by creating an object of type Oficio
, set the Himno
object in correct a way. Try this:
Oficio oficio = new Oficio();
Himno himno = new Himno();
himno.setTexto("Your Text");
oficio.setHimno(himno);
docRef.set(oficio);
I'm misunderstanding things about it?
Yes. To able to manage a Cloud Firestore database, you should have at least basic understanding on:
texto
from the class Himno
does not have a public getter (of the same type). Your getter returns a Spanned
.
Himno
:public String getTexto() {
return this.textTo;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With