Plain Old Java Firebaseからシリアル化され、Firebaseに逆シリアル化されることを意図したオブジェクトを作成している場合、ServerValue.TIMESTAMP
値を使用する方法はありますか?
たとえば、プロパティの1つが最後に編集されたときのオブジェクトがあり、ServerValue.TIMESTAMP
値を使用したいとします。
POJOクラスでは、次のようになります。
private String timeLastChanged;
または
private Map<String, String> timeLastChanged;
String
を使用した最初の例では、timeLastChange = ServerValue.TIMESTAMP;
がマップであるため、ServerValue.TIMESTAMP
の設定の問題に遭遇します。
Map<String, String>
を使用した2番目の例では、データベースに保存されているlongをMap<String, String>
に正しくデシリアライズできないため、「デバウンスに失敗しました」エラーが発生します。これに対する回避策はありますか?
更新12/27/2016
@JsonIgnoreを @ Exclude に切り替え、多くの人が言及しました。
ようやく、DatesとServerValue.TIMESTAMPを操作するための柔軟なソリューションを思い付きました。これは Ivan V 、 Ossama 、および puf の例で機能しています。
long
とHashMap<String, String>
の間の変換を処理する方法を理解できませんでしたが、より一般的なHashMap<String, Object>
でプロパティをネストすると、どちらかとしてデータベースに入ることができます単一のlong値( "date"、 "1443765561874")またはServerValue.TIMESTAMP
ハッシュマップ( "date"、{".sv"、 "servertime"})として。次に、それを引き出すと、常に( "date"、 "some long number")を持つ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 https://stackoverflow.com/questions/25500138/Android-chat-crashes-on-datasnapshot-getvalue-for-timestamp/25512747#25512747
// 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 HashMap<String, Object> getDateLastChanged() public HashMap<String, Object> getDateCreated()
を削除します。そのためには、dateCreated
プロパティに_@JsonProperty
_アノテーションを付けることができます。これを行う別の可能な方法は、そのようなプロパティ検出を変更することです:@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
2番目に、_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;
}
人間が読めるものを取得するには、戻り値の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);
}
私の解決策に関する意見へようこそ^^
@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では、結果は次のようになります。 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つの異なるフィールドを処理するという面倒な作業を省くことができました
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)
}
}