当前位置: 首页 > 知识库问答 >
问题:

从Firestore读取嵌套对象时“RuntimeException:无法反序列化对象”

丁鹏鹍
2023-03-14
{
    "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": {
  ... 


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;
    }
// ...
}


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
        }
    });

E/AndroidRuntime:致命异常:主进程:org.my.app,PID:10532 java.lang.RuntimeException:无法反序列化对象。无法将com.google.firebase.firestore.documenttype对象转换为类型org.my.app.model.himno(在“himno”字段中找到)(位于com.google.firebase.firestore.util.CustomClassMapper.Deserializeerror(com.google.firebase:firebase-firestore@@17.1.2:524)(位于com.google.firebase.firestore.util.CustomClassMapper.ConvertBean7.1.2:674)在com.google.firebase.firestore.util.CustomClassMapper.ConvertBean(com.google.firebase:firebase-firestore@@17.1.2:503)在com.google.firebase.firestore.util.CustomClassMapper.DeserializeToClass(com.google.firebase:firebase-firestore@@17.1.2:242)在

共有1个答案

解飞语
2023-03-14

您将得到以下错误:

无法将类型为com.google.firebase.firestore.documentreference的对象转换为类型为org.my.app.model.himno(在“himno”字段中找到)

因为您正在尝试将DocumentReference对象转换为Himno对象。在Java中没有办法实现这一点,因为它们之间没有继承关系。

您试图从以下位置获取的文档:

db.collection("liturgia").document("breviario").collection("oficio").document("20190204");

类型为oficio,因此以下代码行:

Oficio oficio = documentSnapshot.toObject(Oficio.class);

会工作得很好。问题是当您试图获取Himno对象时,该对象嵌套在Oficio类下,如下所示:

Himno himno=oficio.getHimno();

这将无法按照您的方式工作,因为文档中的Himno属性包含的值类型为DocumentReference而不是Himno

请参见,himno属性有一个引用。如果要获取文档引用,只需使用:

DocumentReference documentReference = documentSnapshot.getDocumentReference("himno");

如果要使用:

Himno himno=oficio.getHimno();

然后将Himno属性更改为Himno类型,而不是DocumentReference类型。

正如@anees在他的aswer中指出的,您的代码中的另一个问题是getTexto()方法应该返回一个String而不是一个spanned对象,因为这是数据库中存储的方式。

请参见,texto属性保存的是字符串,而不是spanned。但这并不是您的错误发生的原因。

还请注意,以下句子:

Firestore中的自定义类必须包含

public class Oficio {
    public Invitatorio invitatorio;
    public Himno himno;
    public Salmodia salmodia;
    public String oracion;
    public String responsorio;
    public OficioLecturas oficioLecturas;
}

编辑:

根据你的评论:

我将getTexto()的类型从spaned更改为String,但不起作用。

仅将getTexTo()方法的返回类型从spanned更改为String不会帮助您解决主要错误。

我不明白如何将himno属性更改为类型为himno而不是DocumentReference。

您没有分享将数据添加到数据库的方式,但实际上非常简单。首先,从这些文档中删除himno属性。然后,在添加新文档时,不是添加DocumentReference,而是添加Himno类型的对象,正如我还看到您在Oficio类中声明的那样。这也意味着,当您使用以下代码行时:

Himno himno=oficio.getHimno();

将返回Himno类型的对象,而不是DocumentReference。这是因为它是根据其数据类型存储的。

在RealTimeDatabase中,可以只获取一个对象(Oficio par示例),并且可以从该对象获取对另一个嵌套对象的引用(Himno par示例)。

这也可以在Cloud Firestore中完成,但您需要根据数据库中存在的属性的数据类型获取数据。如果属性的类型为DocumentReference,则不能将其作为Himno类型获取,除非您这样添加它。

请参阅文档中的“自定义对象”部分

是的,我明白了。这就是为什么我告诉您要根据数据存储的数据类型获取数据的原因。因此,如果您将数据存储为DocumentReference,请根据它获取数据。如果您希望以himno的形式获取它,那么首先将其存储为himno并相应地获取它。

编辑2:

是的,你能做到。您是如何在数据库中添加该引用的?以与添加引用相同的方式添加himno对象。

我不明白我怎么能做到这一点。

当您通过创建OFICIO类型的对象向数据库添加数据时,请以正确的方式设置Himno对象。试试看:

Oficio oficio = new Oficio();
Himno himno = new Himno();
himno.setTexto("Your Text");
oficio.setHimno(himno);
docRef.set(oficio);

我误会了?

是的。要能够管理云Firestore数据库,您至少应该对以下方面有基本的了解:

  • 如何在Java中创建对象
  • 如何设置对象属性
  • 如何将数据添加到Cloud FireStore
  • 什么是集合/文档
  • FireStore中允许的数据类型
 类似资料:
  • 我不能读取属性作为自定义类'Himno'。当我尝试时,即使我注释一行,我也会得到一个“运行时间异常”:。然而,我可以得到属性到相应的变量。 E/AndroidRuntime:致命异常:主进程:组织。我的应用程序,PID:10532 java。lang.RuntimeException:无法反序列化对象。无法转换com类型的对象。谷歌。火基。消防商店。文档引用类型org。我的应用程序。模型Himno

  • 问题内容: 我有一个名为的类,该类具有一个作为参数的构造函数: 具有以下属性: 并且是我的应用程序的其他类,并具有以下构造函数: ,并且是的子类。 我想用Gson 反序列化数组,所以我写道: 以定义为: 调试时,实例具有正确的“ MainActivity”作为上下文,而其成员变量的上下文为null。 Gson 使用正确的构造函数创建了对象,但使用默认的无参数构造函数创建了实例。我怎样才能解决这个问

  • 我有一个名为PageItem的类,它有一个构造函数,该构造函数将上下文作为参数: 具有以下属性: 新闻提供者(Newsprovider)和主题(Topic)是我的应用程序的其他类,具有以下构造函数:

  • 但它返回一个id为空且产品为空的对象。当然,我不需要为这个简单的操作编写自定义的吗?

  • (数据类)实体。JAVA (数据类)实体。JAVA 我试着说: 我犯了一个错误: 我已经把和我错过了什么?

  • 我对对象接口的jackson序列化有问题。 我有课 哪个实现 还有上课 哪个实现 上课 我要和Jackson连载Container得到结果 但事实上我得到了结果 尽管我在映射中指定了点的序列化类型(),但在嵌套对象“point”中具有属性“name”。接口点视图没有方法getName,但结果中存在点的字段“name”。 若我从类容器中的方法getMap中删除注释(),我将得到结果 现在点没有属性"