在Firebase中制作POJO时,可以使用ServerValue.TIMESTAMP吗?

When making a POJO in Firebase, can you use ServerValue.TIMESTAMP?

当您制作一个要从 Firebase 序列化和反序列化到 Firebase 的普通旧 Java 对象时,有没有办法使用 ServerValue.TIMESTAMP 值?

例如,假设我想要一个对象,其中一个属性是上次编辑它的时间,而您想要使用 ServerValue.TIMESTAMP 值。

在 POJO class 中,您可能有:

private String timeLastChanged;

private Map<String, String> timeLastChanged;

在第一个例子中用String,我运行进入设置timeLastChange = ServerValue.TIMESTAMP;的问题,因为ServerValue.TIMESTAMP是一个Map。

在带有 Map<String, String> 的第二个示例中,我收到 "failed to debounce" 错误,因为它无法将数据库中存储的 long 正确反序列化为 Map<String, String>。有什么解决办法吗?

2016 年 12 月 27 日更新

正如许多人提到的那样,为 @Exclude 关闭了 @JsonIgnore。


我终于想出了一个灵活的解决方案来处理日期和 ServerValue.TIMESTAMP。这是基于 Ivan V, Ossama, and puf 中的示例。

我想不出一种方法来处理 longHashMap<String, String> 之间的转换,但是如果您将 属性 嵌套在更通用的 HashMap<String, Object> 中它可以作为单个长值("date"、“1443765561874”)或作为 ServerValue.TIMESTAMP 散列映射("date"、{".sv"、"servertime"}).那么拉出来的时候,永远是一个带("date","some long number")的HashMap。然后,您可以使用 @JsonIgnore @Exclude 注释在 POJO class 中创建一个辅助方法(这意味着 Firebase 将忽略它并且不会将其视为序列化方法 to/from 数据库)轻松从返回的 HashMap 中获取 long 值以在您的应用中使用。

POJO class 的完整示例如下:

import com.google.firebase.database.Exclude;
import com.firebase.client.ServerValue;

import java.util.HashMap;
import java.util.Map;

public class ExampleObject {
    private String name;
    private String owner;
    private HashMap<String, Object> dateCreated;
    private HashMap<String, Object> dateLastChanged;

    /**
     * Required public constructor
     */
    public ExampleObject() {
    }

    public ExampleObject(String name, String owner, HashMap<String,Object> dateCreated) {
        this.name = name;
        this.owner = owner;
        this.dateCreated = dateCreated;

        //Date last changed will always be set to ServerValue.TIMESTAMP
        HashMap<String, Object> dateLastChangedObj = new HashMap<String, Object>();
        dateLastChangedObj.put("date", ServerValue.TIMESTAMP);
        this.dateLastChanged = dateLastChangedObj;
    }

    public String getName() {
        return name;
    }

    public String getOwner() {
        return owner;
    }

    public HashMap<String, Object> getDateLastChanged() {
        return dateLastChanged;
    }

    public HashMap<String, Object> getDateCreated() {
      //If there is a dateCreated object already, then return that
        if (dateCreated != null) {
            return dateCreated;
        }
        //Otherwise make a new object set to ServerValue.TIMESTAMP
        HashMap<String, Object> dateCreatedObj = new HashMap<String, Object>();
        dateCreatedObj.put("date", ServerValue.TIMESTAMP);
        return dateCreatedObj;
    }

// Use the method described in 
// to get the long values from the date object.
    @Exclude
    public long getDateLastChangedLong() {

        return (long)dateLastChanged.get("date");
    }

    @Exclude
    public long getDateCreatedLong() {
        return (long)dateCreated.get("date");
    }

}

我想稍微改进一下 Lyla 的回答。首先,我想摆脱 public 方法 public HashMap<String, Object> getDateLastChanged() public HashMap<String, Object> getDateCreated()。为此,您可以使用 @JsonProperty 注释标记 dateCreated 属性。另一种可能的方法是像这样更改 属性 检测:@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
其次,我不明白为什么我们需要将 ServerValue.TIMESTAMP 放入 HashMap 而我们可以将它们存储为 属性。所以我的最终代码是:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.firebase.client.ServerValue;

public class ShoppingList {
    private String listName;
    private String owner;
    @JsonProperty
    private Object created;

    public ShoppingList() {
    }

    public ShoppingList(String listName, String owner) {
        this.listName = listName;
        this.owner = owner;
        this.created = ServerValue.TIMESTAMP;
    }

    public String getListName() {
        return listName;
    }

    public String getOwner() {
        return owner;
    }

    @JsonIgnore
    public Long getCreatedTimestamp() {
        if (created instanceof Long) {
            return (Long) created;
        }
        else {
            return null;
        }
    }

    @Override
    public String toString() {
        return listName + " by " + owner;
    }

}

这些解决方案对我来说似乎有点困难,因为我不知道@JsonIgnore 在做什么。我试着用一种简单的方式来做,看起来很管用。

private Object dateLastChanged;

public Object getDateLastChanged() {
    return dateLastChanged;
}

为了获得人类可读的内容,我只是将 return 值 dateLastChanged 对象转换为 Long,从而将其传递到以下方法中。

static String convertTime(Long unixtime) {
    Date dateObject = new Date(unixtime);
    SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MM-yy hh:mmaa");
    return dateFormatter.format(dateObject);
}

欢迎对我的方案提出意见^^

您可以使用 Firebase 本机 @Exclude,而不是使用 @JsonIgnore。 比如我在做一个类似的项目,我的模型是这样的

package com.limte.app.borrador_1.mModel;

import com.google.firebase.database.Exclude;
import com.google.firebase.database.ServerValue;

/**
 * Created by Familia on 20/12/2016.
 */

public class ChatItem {
    String chatName;
    Long creationDate;


    public ChatItem() {
    }

    public String getChatName() {
        return chatName;
    }

    public void setChatName(String chatName) {
        this.chatName = chatName;
    }

    public java.util.Map<String, String> getCreationDate() {
        return ServerValue.TIMESTAMP;
    }

    @Exclude
    public Long getCreationDateLong() {
        return creationDate;
    }
    public void setCreationDate(Long creationDate) {
        this.creationDate = creationDate;
    }

}

并且此代码有效!在 Firebase 中,结果是: Results

相同的解决方案,但我使用这个。

@IgnoreExtraProperties
public class FIRPost {
    Object timestamp;

    public FIRPost() {
        // Default constructor required for calls to DataSnapshot.getValue(FIRPost.class)
        this.timestamp = ServerValue.TIMESTAMP;
    }

    public Object getTimestamp() {
        return timestamp;
    }

    @Exclude
    public Long getTimestamp(boolean isLong) {
        if (timestamp instanceof Long) return (Long) timestamp;
        else return null;
    }
}

Server.TIMESTAMP 最常见的用法是:

  1. 设置数据发送到服务器时的服务器值
  2. 从 firebase 获取此模型,并轻松将其转换为 Long

这个技巧让我免去了为 1 个值处理 2 个不同字段的辛苦工作

    public class HandleTimestampFirebaseObject {

    Object timestamp;

    public HandleTimestampFirebaseObject() {

    }

    public Object getTimestamp(){
        if(timestamp instanceof Double){

      /*    this will handle the case of AFTER fetch from backend,and  
            serialize to object into SharedPreferences for example ,when the 
            Object casting automatically into Double.
            (Anyway,call (long)getTimestamp from your code who use this model*/
            return ((Double) timestamp).longValue();
        }
        else{
            return timestamp;  //this handle to firebase requirement in the server side(Object needed)
        }
    }