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

时间:2019-11-16 06:45:27

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

我收到此错误消息

  

java.lang.RuntimeException:无法反序列化对象。无法将类型java.util.ArrayList的值转换为String(在字段“ 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中,在同一父键下同时具有整数值和列表值似乎是必需的。)

    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

我感谢任何出于纯粹利他主义精神而花时间阅读此意大利面条式代码的人。

1 个答案:

答案 0 :(得分:1)

我认为您必须特别指出要反序列化的字段。 例如,在onSuccess内部

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

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

我没有测试它,我希望它能工作))