火力基地"Map while deserializing, but got a class java.util.ArrayList"



我只是在Android上为我的项目尝试Firebase。

遇到的问题是,每次我拍摄快照并将其"投射"回 POJO 时,我都会得到这个 -

"反序列化时映射,但得到一个类java.util.ArrayList"异常。

我一直在环顾四周,甚至使用HashMap更改我所有的模型,没有任何ArrayList,但仍然得到相同的结果。

这是我的模型:

  public class DevicesController {
        public DevicesCollection devices;
        public int numberOfport;
        String timerStatus;
        public DevicesController(){
            devices = new DevicesCollection();
            timerStatus = "UPDATED";
        }
        public DevicesController(int numberOfport){
            devices = new DevicesCollection();
            this.numberOfport = numberOfport;
            timerStatus = "UPDATED";
        }

        public ArrayList<Integer> getCurrentState(String in){
            ArrayList<Integer> currentState = new ArrayList<Integer>();
            for(int i = 0; i < numberOfport; i++){
                currentState.add(0);
            }
            Iterator it = this.getDevices().getAllDevices().entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry pair = (Map.Entry) it.next();
                Device temp =(Device)pair.getValue();
                if(temp.isOn()){
                    currentState.set(temp.getPort(),1);
                }else if(!temp.isOn()){
                    currentState.set(temp.getPort(),0);
                }
            }
            return currentState;
        }

        public String getStringCurrentState(String in){
            ArrayList<Integer> currentState = getCurrentState("");
            String temp ="";
            for(int i = 0; i < currentState.size();i++){
                temp.concat(""+currentState.get(i));
            }
            return temp;
        }
        public void updateToDb(){
            Global.dbMRoot.child("devicesController").setValue(this);
        }
        public DevicesCollection getDevices() {
            return devices;
        }
        public int getNumberOfport() {
            return numberOfport;
        }
    }
    public class Category {
        public String name;
        public HashMap<String,String> devicesId;
        public DeviceAlarm categoryAlarm;
        public Category(){
        }
        public Category(String name) {
            devicesId = new HashMap<String,String>();
            this.name = name;
        }
        public void addDevice(Device dev){
            devicesId.put(dev.getId(),dev.getId());
        }

        public void removeDevice(Device dev){
            devicesId.remove(dev.getId());
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public HashMap<String,String> getDevicesId() {
            return devicesId;
        }
        public void setDevicesId(HashMap<String,String> devicesId) {
            this.devicesId = devicesId;
        }
    }
public class Device {
    public String id;
    public int port;
    public String name;
    public boolean on;
    public  DeviceAlarm alarm;
    public Device(){
    }

    public Device(String id,String name){
        this.id = id;
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
        updateToDb();
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        updateToDb();
        this.name = name;
    }
    public boolean isOn() {
        return on;
    }
    public void setOn(boolean on) {
        updateToDb();
        this.on = on;
    }
    public void updateToDb(){
        Global.dbMRoot.child("devicesController").child("devices").child("allDevice").child(""+id).setValue(this);
    }
    public DeviceAlarm getTimer() {
        return alarm;
    }

    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        updateToDb();
        this.port = port;
    }
    public DeviceAlarm getAlarm() {
        return alarm;
    }
    public void setAlarm(DeviceAlarm alarm) {
        Global.dbMRoot.child("devicesController").child("timerStatus").setValue("CHANGED");
        this.alarm = alarm;
        updateToDb();
    }
    public void setAlarm(boolean active, Calendar timeOn, Calendar timeOff) {
        Global.dbMRoot.child("devicesController").child("timerStatus").setValue("CHANGED");
        DeviceAlarm temp = new DeviceAlarm();
        temp.setTimeOff(timeOff);
        temp.setTimeOn(timeOn);
        this.alarm = temp;
        updateToDb();
    }
}

package com.lucerna.afgadev.lucerna_maincontroller.Models;
import com.lucerna.afgadev.lucerna_maincontroller.Global;
import java.util.ArrayList;
import java.util.HashMap;
/**
 * Created by aufa on 06/07/2016.
 */
public class DevicesCollection {
    public HashMap<String,Device> allDevices;
    public HashMap<String,Category>  categories;
    int lastId;
    public DevicesCollection(){
        categories = new HashMap<String,Category>();
        lastId = 0;
        allDevices = new HashMap<String, Device>();
    }
    public HashMap<String,Category> getCategories() {
        return categories;
    }
    public HashMap<String,Device> getAllDevices() {
        return allDevices;
    }
    public void addCategory(String name){
        categories.put(name,new Category(name));
    }
    public void removeCategory(String name) throws Exception{
        int index = -1;
        for(int i = 0; i< categories.size(); i++){
            if(categories.get(i).getName().equals(name)){
                index = 1;
            }
        }
        if(index == -1){
            throw new Exception("Category not found");
        }else{
            categories.remove(index);
        }
        updateToDB();
    }
    public void updateToDB(){
        Global.dbMRoot.child("devicesController").child("devices").setValue(this);
    }
    public Category findCategory(String name){
        Category temp = null;
        for(int i = 0; i< this.getCategories().size(); i++){
            if(this.getCategories().get(i).getName().equals(name)){
                temp = this.getCategories().get(i);
            }
        }
        return temp;
    }
    public void switchCategory(String name, boolean on){
        Category cat = findCategory(name);
        for(int i = 0; i < cat.getDevicesId().size();i++){
        }
    }

    public void addDevice(String name, int port){
        Device temp = new Device();
        temp.setPort(port);
        temp.setName(name);
        allDevices.put(""+lastId,temp);
        this.lastId++;
        Global.dbMRoot.child("devicesController").child("devices").child(""+lastId).setValue(allDevices.get(lastId));
    }
    public void removeDevice(int id){
        allDevices.remove(id);
        updateToDB();
    }
    public void setCategoryDevicesAlarm(DeviceAlarm da){
    }
}

示例 JSON 树 GDrive

我仍然不知道为什么会发生这种情况,我已经重新检查以确保没有一个是 ArrayList(我知道 firebase 应该支持 arrayList)

感谢您的所有评论和回答!

我有一个部分答案,但需要弗兰克的专业知识来解释到底发生了什么。

使用版本 9.2.0 运行发布的代码,我观察到allDevicesHashMap存储为 JSON 数组:

public class DevicesCollection {
    public HashMap<String,Device> allDevices; <-- this is stored as array
    public HashMap<String,Category>  categories;
    int lastId;

这在Aufa发布的JSON中可见:

{
  "devicesController" : {
    "devices" : {
      "allDevices" : [ { <-- note bracket
        "name" : "",
        "on" : true,
        "port" : 0
      }, {

这似乎是因为allDevices元素的键是整数形式的字符串。 这是向allDevices映射添加条目的代码:

public void addDevice(String name, int port){
    Device temp = new Device();
    temp.setPort(port);
    temp.setName(name);
    allDevices.put(""+lastId,temp); <-- Note that lastId is an integer
    this.lastId++;
    Global.dbMRoot.child("devicesController").child("devices").child(""+lastId).setValue(allDevices.get(lastId));
}

如果将此代码修改为使用非整数格式的 String 键,例如:

allDevices.put("ID"+lastId,temp);

然后将地图写成地图,可以使用

getValue(DevicesCollection.class);

我也遇到了同样的错误。但后来我才知道,起初,我在 Note.kt 数据类中使用了 List 的 tags 变量并将其存储在 firestore 文档中,但后来我用 Map tags更改了相同的变量名称并尝试从 firestore 获取数据。在 firestore 中,我与列表和地图tags名称相同,因此在从 firestore 获取数据时出现错误。当我删除集合并再次添加数据时,我的问题解决了。

注意.kt

 data class Note(
 //val tags:List<String>? = null, //first with tags variable 
 val tags:Map<String,Any>? = null, //second with same tags variable

如果你像这样映射:

    basketRef.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            if(dataSnapshot.value==null || dataSnapshot.value!!.equals(""))
                Enums.userBasket=UserItem()
            else
                Enums.userBasket = dataSnapshot.getValue(UserItem::class.java)
        }
        override fun onCancelled(p0: DatabaseError) {
            // Failed to read value
            Log.d(TAG, "Error= "+p0.message)
        }
    })

在 Firebase 设备中,id 元素子级像(-1:"",-2:"")

Firebase Android SDK认为这是一个ArrayList而不是Map Object。

下面的代码对我来说效果很好。我不能使用上面的代码。

Enums.userBasket=UserItem()
    basketRef.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            if(dataSnapshot.value==null || dataSnapshot.value!!.equals(""))
            else{
                if(dataSnapshot.child("books")!=null){
                    dataSnapshot.child("books").children.forEach {
                        Enums.userBasket!!.books[it.key.toString()] =it.value.toString()
                    }
                }
                if(dataSnapshot.child("cards")!=null){
                    dataSnapshot.child("cards").children.forEach {
                        Enums.userBasket!!.cards[it.key.toString()] =it.value.toString()
                    }
                }
                if(dataSnapshot.child("exams")!=null){
                    dataSnapshot.child("exams").children.forEach {
                        Enums.userBasket!!.exams[it.key.toString()] =it.value.toString()
                    }
                }
            }
        }
        override fun onCancelled(p0: DatabaseError) {
            // Failed to read value
            Log.d(TAG, "Error= "+p0.message)
        }
    })

我的用户项类:

 @IgnoreExtraProperties
data class UserItem(
    var books:MutableMap<String,String> = HashMap(),//id,value
    var cards:MutableMap<String,String> = HashMap(),//id,value
    var exams:MutableMap<String,String> = HashMap()//id,value
)

或者你可以看看这个 链接.火力部队使用地图而不是阵列

相关内容

最新更新