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

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


我不能读取属性himno作为自定义类'Himno'。当我尝试时,即使我注释一行,我也会得到一个“运行时间异常”:Himno himno=oficio.getHimno();。然而,我可以得到属性oracion到相应的变量。


E/AndroidRuntime:致命异常:主进程:组织。我的应用程序,PID:10532 java。lang.RuntimeException:无法反序列化对象。无法转换com类型的对象。谷歌。火基。消防商店。文档引用类型org。我的应用程序。模型Himno(在字段“Himno”中找到)位于com.google.火基。消防商店。util。自定义类映射器。com上的反序列化错误(com.google.firebase:firebase firestore@@17.1.2:524)。谷歌。火基。消防商店。util。自定义类映射器。convertBean(com.google.firebase:firebase firestore@@17.1.2:505)位于。谷歌。火基。消防商店。util。自定义类映射器。反序列化ZetoClass(com.google.firebase:firebase firestore@@17.1.2:242)位于com.google.火基。消防商店。util。自定义类映射器。在com上反序列化类型(com.google.firebase:firebase firestore@@17.1.2:180)。谷歌。火基。消防商店。util。自定义类映射器。在com上访问$200(com.google.firebase:firebase firestore@@17.1.2:53)。谷歌。火基。消防商店。util。CustomClassMapper$BeanMapper。在com上反序列化(com.google.firebase:firebase firestore@@17.1.2:700)。谷歌。火基。消防商店。util。CustomClassMapper$BeanMapper。在com上反序列化(com.google.firebase:firebase firestore@@17.1.2:674)。谷歌。火基。消防商店。util。自定义类映射器。convertBean(com.google.firebase:firebase firestore@@17.1.2:503)位于。谷歌。火基。消防商店。util。自定义类映射器。反序列化ZetoClass(com.google.firebase:firebase firestore@@17.1.2:242)位于com.google.火基。消防商店。util。自定义类映射器。convertToCustomClass(com.google.firebase:firebase firestore@@17.1.2:97)位于com.google.火基。消防商店。文档快照。toObject(com.google.firebase:firebase firestore@@17.1.2:203)位于。谷歌。火基。消防商店。文档快照。toObject(com.google.firebase:firebase-firestore@@17.1.2:183)

共有2个答案

席烨
2023-03-14
  • 一个公共默认构造函数(不接受参数的构造函数)
  • 每个属性的公共getters(相同类型)

Himno中的texto没有公共getter(相同类型)。您的getter返回一个已跨越的

public String getTexto() {
    return this.textTo;
}

傅献
2023-03-14

您将收到以下错误:

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

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

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

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

属于Oficio的类型,因此以下代码行:

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

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

Himno himno=oficio.getHimno();

这将不会以您的方式工作,因为文档中的himno属性包含一个DocumentReference类型的值,而不是himno类型的值。

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

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

如果你想使用:

Himno himno=oficio.getHimno();

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

代码中的另一个问题,也正如@Anes在他的aswer中指出的那样,是getTexas to()方法应该返回一个String而不是一个跨越的对象,因为这是存储在数据库中的方式...

请参见,texto属性包含一个字符串,而不是一个跨越的。但这并不是发生错误的原因。

还请注意,以下句子:

Firestore中的自定义类必须包含

这是不对的!对于公共无参数构造函数或公共获取者来说,没有必要这样做。

所以你的类可能看起来像这样:

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

没有任何构造函数、setter或getter。更多信息在这里。

编辑:

根据你的评论:

我将getTexas to()的类型从跨越改为字符串,但不起作用。

仅将getTexto()方法的返回类型从span更改为String将无助于解决主要错误。

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

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

Himno himno=oficio.getHimno();

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

在RealTimeDatabase中,只有一个对象(OFICIO PAR示例)是可能的,并且从这个对象中,我可以得到另一个嵌套对象(HimNO-PAR示例)的引用。

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

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

是的,我明白了。这就是为什么我告诉您根据存储的数据类型获取数据。因此,如果您将数据存储为文档引用,请根据它获取数据。如果要将其作为Himno获取,请首先将其存储为Himno,然后相应地获取它。

编辑2:

你是在告诉我,在火力恢复中可以创建一个Himno类型的字段吗?

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

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

通过创建类型为Oficio的对象向数据库添加数据时,请以正确的方式设置Himno对象。试试这个:

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

我误解了这件事?

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

  • 如何在Java中创建对象
  • 如何设置对象属性
  • 如何向云Firestore添加数据
  • 什么是收藏/文件
  • Firestore中允许的数据类型
 类似资料:
  • E/AndroidRuntime:致命异常:主进程:org.my.app,PID:10532 java.lang.RuntimeException:无法反序列化对象。无法将com.google.firebase.firestore.documenttype对象转换为类型org.my.app.model.himno(在“himno”字段中找到)(位于com.google.firebase.fires

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

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

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

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

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