java - 无法从 Firestore 读取自定义对象 - 为什么?

标签 java android google-cloud-firestore runtime-error

我收到此错误消息

java.lang.RuntimeException: Could not deserialize object. Failed to convert value of type java.util.ArrayList to String (found in field 'allNames')

当我尝试将文档从 Firestore 读取到自定义对象 DBStructure.class 时。

这是我用来检索数据的代码:


    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private DocumentReference DBStructureDocRef = db.document(DB_STRUCTURE_PATH);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRoom = new Room();
        mDBStructure = new DBStructure();

        readData();
        HandleSpinnerSelection("", -1);
    }

    private void readData() {
        DBStructureDocRef.get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if (documentSnapshot.exists()) {
                            **mDBStructure = documentSnapshot.toObject(DBStructure.class)**;
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, e.toString());
                    }
                });
    }

这是 DBStructure.class。

    public class DBStructure {

    List<String> allTypes = new ArrayList<>();
    List<String> allNames = new ArrayList<>();
    List<String> allSurfaces = new ArrayList<>();
    Map<String, Map<String, Unit>> hospitalLayout = new HashMap<>();

    public DBStructure() {
    }

    public DBStructure(String allTypes, String allNames, List<String> allSurfaces, Map<String, Map<String, Unit>> hospitalLayout) {
        setAllTypes(allTypes);
        setAllNames(allNames);
        setAllSurfaces(allSurfaces);
        this.hospitalLayout = hospitalLayout;
    }

    public List<String> getAllTypes() {
        return allTypes;
    }

    public void setAllTypes(String newType) {
        allTypes.add(newType);
    }

    public List<String> getAllNames() {
        return allNames;
    }

    public void setAllNames(String newName) {
        allNames.add(newName);
    }

    public List<String> getAllSurfaces(){
        return allSurfaces;
    }
    public void setAllSurfaces(List<String> surfaces) {
        // Ugly but easy gymnastics to avoid duplicates
        HashSet<String> allSurfacesSet = new HashSet<>(this.allSurfaces);
        for (String surface : surfaces)
            allSurfacesSet.add(surface);
        List<String> allSurfaces = new ArrayList<>(allSurfacesSet);
        this.allSurfaces = allSurfaces;
    }

    public Map<String, Map<String, Unit>> getHospitalLayout() {
        return hospitalLayout;
    }

    public void setHospitalLayout(String unitType, String unitName, long first, long last, List<String> surfaces) {
        Map<String, Map<String, Unit>> hospitalLayout = new HashMap<>();
        Map<String, Unit> nameRoomsSurfaces = new HashMap<>();
        Unit roomsSurfaces = new Unit();
        roomsSurfaces.setUnit(first, last, surfaces);
        nameRoomsSurfaces.put(unitName, roomsSurfaces);
        hospitalLayout.put(unitType, nameRoomsSurfaces);
        this.hospitalLayout = hospitalLayout;

        setAllTypes(unitType);
        setAllNames(unitName);
        setAllSurfaces(surfaces);
    }

    public Map<String, Unit> getUnitNamesRoomsSurfaces(String type, Map<String, Map<String, Unit>> hospitalLayout){
        // Extracts the namesRoomsSurfaces from the HospitalLayout using the passed Type
        Map<String, Map<String, Unit>> layout = hospitalLayout;
        Map<String, Unit> namesRoomsSurfaces = layout.get(type);
        return namesRoomsSurfaces;
    }

    public Unit getRoomsSurfaces (String name, Map<String, Unit> nameRoomsSurfaces){
        return nameRoomsSurfaces.get(name);
    }
}

(Unit 是第二个类,它似乎需要在 DBStructure HashMap 中的同一父键下同时具有整数和 List 值)。

    public class Unit {
    // Defines the unit Name-Rooms-Surfaces
    Long firstRoom;
    Long lastRoom;
    List<String> surfaceList = new ArrayList<>();
    //Unit mUnit = new Unit();

    public Unit() {
    }


    public void setUnit (long firstRoom, long lastRoom, List<String> surfaceList) {
        this.firstRoom = firstRoom;
        this.lastRoom = lastRoom;
        this.surfaceList = surfaceList;
    }

    public Long getFirstRoom() {
        return firstRoom;
    }

    public Long getLastRoom() {
        return lastRoom;
    }

    public List<String> getSurfaceList() {
        return surfaceList;
    }

} 

...最后,这是 Firestore 中数据的样子,由简单的 .set(mDBStructure) 编写

Data set with three lists and one nested hashmap

我感谢所有出于纯粹的利他主义而花时间阅读这段意大利面条代码的人。

最佳答案

我认为你必须明确指出你要反序列化的字段。 例如,在您的情况下,在 onSuccess 内

DocumentSnapshot document = documentSnapshot.getResult();
DbStructure db = new DbStructure();
db.setAllNames((List<String>) document.get("allNames"));
db.setAllTypes((List<String>) document.get("allTypes"));` 

等等。在这种情况下,当反序列化返回的对象时,不会发生冲突。顺便说一句,在您的 setter 中,您必须将参数更改为列表类型)))。

我没有测试它,我希望它有效))

关于java - 无法从 Firestore 读取自定义对象 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58888280/

相关文章:

swift - 我无法使用具有 3 个选项的 UIPickerView 查询 Firestore

AngularFire Firestore 属性 'map' 在类型 'Action<DocumentSnapshot<any>>' 上不存在

java - 如何避免创建多余的实体?

android - 运行 Android 应用程序的最低要求

android - 在 onResume() 之前动态更改 DialogFragment Max_Height?

java - 变音符号 (äöü) 的奇怪编码

firebase - 在Firestore中按ID提取多个文档

java - Spring Boot执行器端点映射根类

java - 使用java解方程

java - 我如何在一秒内实时获得蓝牙 RSSI 10 次,持续 10 秒