Firebase“反序列化时映射,但得到类java.util.ArrayList”

时间:2016-07-07 19:09:52

标签: java android json firebase-realtime-database pojo

我只是在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)

感谢所有的评论和答案!

3 个答案:

答案 0 :(得分:10)

我有一个部分答案,但需要弗兰克的专业知识来解释实际情况。

使用版本9.2.0运行发布的代码,我发现HashMap的{​​{1}}存储为JSON数组:

allDevices

这在Aufa发布的JSON中可见:

public class DevicesCollection {

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

这似乎是因为{ "devicesController" : { "devices" : { "allDevices" : [ { <-- note bracket "name" : "", "on" : true, "port" : 0 }, { 元素的键是整数形式的字符串。这是在allDevices

地图中添加条目的代码
allDevices

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

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

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

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

答案 1 :(得分:0)

如果您要这样映射:

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

    })

我的UserItem类:

 @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
)

或者您可以查看此链接。 Firebase force to use map rather than array

答案 2 :(得分:0)

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

Note.kt

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

)