首页 > 解决方案 > Firebase 对象与 Java 类的子对象

问题描述

我正在尝试从 relatime 数据库中读取以下对象

从 Firebase 导出的 JSON 是这样的:

"categorias" : {
    "Telas de Hogar" : {
      "descripcion" : "",
      "estado" : "invisible",
      "nombre" : "Telas de Hogar",
      "paginas" : {
        "Loneta" : {
          "descripcion" : "",
          "estado" : "invisible",
          "nombre" : "Loneta"
        }
      }
    }
  }

当前班级:

package com.example.tejidospulido_app.Model.Classes;
import java.util.Map;

public class Category {
    private String nombre;
    private String descripcion;
    private String estado;
    private Map<String, String> productos;
    private Map<String, Page> paginas;

    public Category(){}

    public Category(String name) {
        this.nombre = "";
        this.descripcion = "";
        this.estado = "";
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    public String getEstado() {
        return estado;
    }

    public void setEstado(String estado) {
        this.estado = estado;
    }

    public Map<String, String> getProductos() {
        return this.productos;
    }

    public void setProductos(Map<String, String> productos) {
        this.productos = productos;
    }

    public Map<String, Page> getPaginas() {
        return this.paginas;
    }

    public void setPaginas(Map<String, Page> pages) {
        this.paginas = paginas;
    }

    @Override
    public String toString() {
        return nombre;
    }
}

我已经设法读取了对象及其属性,但是当我想读取paginasproductos时,它在paginas中返回 null 并在productos中返回thi 错误:

com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(CustomClassMapper.java:426)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:217)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToType(CustomClassMapper.java:179)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToParameterizedType(CustomClassMapper.java:265)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToType(CustomClassMapper.java:177)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$100(CustomClassMapper.java:48)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:593)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:563)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:433)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
        at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
        at com.example.tejidospulido_app.Vista.MenuFragment$2.onDataChange(MenuFragment.java:95)
        at com.google.firebase.database.Query$1.onDataChange(Query.java:189)
        at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
        at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

我已经从不同的来源搜索和阅读,根据我的理解,我应该使用地图,但事实是,我不知道该怎么做......

这是阅读的代码,如果我调试它,后面是调试结果的图像。

FirebaseDatabase.getInstance().getReference().child("categorias").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
            Category c = snapshot.getValue(Category.class);
            list.add(c);
        }
        AdapterCategories adapter = new AdapterCategories(list);
        recycleView.setAdapter(adapter);
    }

    @Override
    public void onCancelled(DatabaseError error) {
        // Failed to read value
        Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show();
    }
});

标签: javaandroidfirebaseclassfirebase-realtime-database

解决方案


The Solution As You Mentioned Is Maps, I Will Help You To Imagine That Let's Start from the simple to complex

Before You Read This Keep in mind that the map is just an object storing key values Like JSON Storing a Key Value

First, This Inner Pagena Object In Json Looks Like

"Loneta" : {
          "descripcion" : "",
          "estado" : "invisible",
          "nombre" : "Loneta"
        }

When You Want To represent that using map it will be

Map<String,String> Loneta = new HashMap();
Loneta.put("descripcion" , "");
Loneta.put("estado" , "invisible");
Loneta.put("nombre" , "Loneta");

So The Loneta Object in JSON Is Now A Map Note That The Key "Loneta" is the map variable name

To Retrieve something from it

String descripcion = Loneta.get("descripcion"); 

Now Lets' Get Deeper

"Telas de Hogar" : {
      "descripcion" : "",
      "estado" : "invisible",
      "nombre" : "Telas de Hogar",
      "paginas" : {
        "Loneta" : {
          "descripcion" : "",
          "estado" : "invisible",
          "nombre" : "Loneta"
        }
      }
    }

"Telas de Hogar" Can Be Represented As Map

We Will Use The Key "Telas de Hogar" As The Variable Name Of The Map Let's Create this Map

Map<String,String> Telas_de_Hogar = new HashMap();
Telas_de_Hogar.put("descripcion" , "");
Telas_de_Hogar.put("estado" , "invisible");
Telas_de_Hogar.put("nombre" , "Telas de Hogar");

When It Comes To "paginas" Key, Take A Minute And Think In That "paginas" is A Key So It Will Be Map Variable Name

Map<String,String> paginas= new HashMap();

Think Again What is should be inside This Map

We Have A Key "Loneta" And It's Values, So We Need A Loneta Map , Remember That We Created it?

So Put it in "paginas" But Here We Need Some Changes pagins is a map of string key and map value containing maps of string string So We Need To Change The Declaration of it TO

Map<String, Map<String,String>> pagins = new HashMap();    
paginas.put("Loneta", Loneta);

"Loneta" Is The Key And Loneta is The Map Object Reference

Put paginas Map inside Telas_de_Hogar Map

Telas_de_Hogar.put("paginas", paginas)

Again "paginas" Is The Key And paginas is The Map Object Reference

Finally The Top Level Key "categorias" Which Containing The Values Of Telas_de_Hogar Map Let's Create it

Map<String,String> categorias= new HashMap();
categorias.put("Telas de Hogar", Telas_de_Hogar);

I Hope My Answer Help You

UPDATE:

If You Want To Use .getValue(YourClass.class); Change that in your Category Class

private Map<String, String> productos;

TO

private Map<String, Map<String, String> productos;

Explaination: The "Pagins" is A Map Of Key String And Map Value of String String

See upove we put Lonita as map in pagins map

"paginas" : {
        "Loneta" : {
          "descripcion" : "",
          "estado" : "invisible",
          "nombre" : "Loneta"
        }

推荐阅读