При создании POJO в Firebase вы можете использовать ServerValue.TIMESTAMP?

Когда вы создаете обычный Java-объект Plain, предназначенный для сериализации и десериализации в Firebase, существует ли способ использовать значение ServerValue.TIMESTAMP?

Например, скажем, я хочу иметь объект, в котором одно из свойств является последним, когда оно было отредактировано, и вы хотите использовать значение ServerValue.TIMESTAMP.

В классе POJO у вас может быть:

private String timeLastChanged;

или

private Map<String, String> timeLastChanged;

В первом примере с String я столкнулся с проблемой установки timeLastChange = ServerValue.TIMESTAMP;, потому что ServerValue.TIMESTAMP - это карта.

Во втором примере с Map<String, String> я получаю сообщение об ошибке "не удалось debounce", потому что он не может должным образом десериализовать длинный, хранящийся в базе данных, в Map<String, String>. Есть ли какая-нибудь работа для этого?

Ответ 1

Обновление 12/27/2016

Выключено @JsonIgnore для @Исключить, о котором многие говорили.


Наконец, я придумал гибкое решение для работы с Dates и ServerValue.TIMESTAMP. Это отработка примеров из Ivan V, Ossama и puf.

Я не мог понять способ преобразования между long и HashMap<String, String>, но если вы вложите свойство в более общий HashMap<String, Object>, он может войти в базу данных как одно длинное значение ( "дата" , "1443765561874" ) или как хэш-карта ServerValue.TIMESTAMP ( "дата" , { ".sv", "servertime" }). Затем, когда вы его вытаскиваете, всегда будет HashMap с ( "дата" , "некоторое длинное число" ). Затем вы можете создать вспомогательный метод в вашем классе POJO, используя аннотацию @JsonIgnore @Exclude (что означает, что Firebase игнорирует ее и не рассматривает ее как метод для сериализации в/из базы данных), чтобы легко получить длинное значение из возвращаемого HashMap для использования в вашем приложении.

Полный пример класса POJO ниже:

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 /questions/240264/android-chat-crashes-on-datasnapshotgetvalue-for-timestamp/1248164#1248164
// 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");
    }

}

Ответ 2

Я хотел немного улучшить Лилу. Во-первых, я хотел бы избавиться от общедоступных методов public HashMap<String, Object> getDateLastChanged() public HashMap<String, Object> getDateCreated(). Для этого вы можете пометить dateCreated свойство с помощью аннотации @JsonProperty. Другой возможный способ сделать это - изменить определение свойств следующим образом: @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;
    }

}

Ответ 3

Мне кажется, что это решение для меня немного сложно, поскольку я не знаю, что делает @JsonIgnore. Я попытался сделать это легко и, похоже, работает.

private Object dateLastChanged;

public Object getDateLastChanged() {
    return dateLastChanged;
}

Чтобы получить что-то доступное для человека, я просто пропустил возвращаемое значение dateLastChanged Object в следующий метод, введя его в Long.

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

Добро пожаловать в мое решение ^^

Ответ 4

Вместо использования @JsonIgnore вы можете использовать род Firebase @Exclude. Например, я работаю в аналогичном проекте, и моя модель похожа на это.

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 результаты: Результаты

Ответ 5

То же решение, но я использую это.

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

Ответ 6

Наиболее распространенное использование для Server.TIMESTAMP:

  • установить значение сервера, когда данные отправлены на сервер
  • извлеките эту модель из firebase и легко отбросьте ее до Long

Этот трюк спас меня от тяжелой работы с двумя разными полями для всего 1 значения

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