Firebase使用Jackson将Java对象序列化为JSON并将JSON反序列化为Java对象。你可以在the Jackson website和这个page about Jackson annotations找到更多关于杰克逊的信息。
在本答案的其余部分中,我们将介绍几种在Firebase中使用Jackson的常用方法。
加载完整的用户
从火力地堡加载用户进入Android的最简单的方法是,如果我们创建了一个完全模仿的JSON属性的Java类:
private static class User {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
@Override
public String toString() { return "User{handle='"+handle+“', name='"+name+"', stackId="+stackId+"\’}”; }
}
我们可以使用这个类在听众:
Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
System.out.println(user.toString());
}
}
@Override
public void onCancelled(FirebaseError firebaseError) { }
});
你可能注意到了User类跟随JavaBean property pattern。每个JSON属性都由User类中的一个字段映射,并且每个字段都有一个公共的getter方法。通过确保所有属性都使用完全相同的名称进行映射,我们确保杰克逊可以自动映射它们。
您还可以通过将Jackson注释放在Java类及其字段和方法上来手动控制映射。我们将介绍下面两个最常见的注释(@JsonIgnore
和@JsonIgnoreProperties
)。
部分加载用户
说你只关心用户的名称和在Java代码中处理。让我们删除stackId
看看会发生什么:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
@Override
public String toString() {
return "User{handle='" + handle + “\', name='" + name + "\’}”;
}
}
如果我们现在作为前将相同的监听器和运行程序,它会抛出一个异常:
Exception in thread "FirebaseEventTarget" com.firebase.client.FirebaseException: Failed to bounce to type
at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:187)
at com.firebase.LoadPartialUsers$1.onDataChange(LoadPartialUsers.java:16)
“无法抖型”表明Jackson无法将JSON反序列化为User对象。在嵌套异常,它告诉我们,为什么:
Caused by: com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stackId" (class com.firebase.LoadPartialUsers$User), not marked as ignorable (2 known properties: , "handle", "name"])
at [Source: [email protected]; line: 1, column: 15] (through reference chain: com.firebase.User["stackId"])
at com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
杰克逊找到了物业stackId
在JSON,不知道该怎么用它做,所以它抛出一个异常。幸运的是,我们可以用它来告诉它映射到我们的User
上课的时候从JSON忽略特定属性的注释:
@JsonIgnoreProperties({ “stackId" })
private static class User {
...
}
如果我们不运行再次与我们的监听器的代码,杰克逊会知道它可以忽略JSON中的stackId
,它将能够将JSON反序列化为User对象。
由于添加属性到JSON在火力地堡应用,例如常见的做法,你会发现它更方便简单地告诉杰克逊忽略不具有Java类的映射所有属性:
@JsonIgnoreProperties(ignoreUnknown=true)
private static class User {
...
}
现在,如果我们稍后将属性添加到JSON,Java代码仍然可以加载User
。请记住,User对象不会包含JSON中存在的所有信息,因此在将它们重新写回到Firebase时请小心。
部分用户节约
原因之一,它是好的,有一个自定义的Java类,就是我们可以添加方便的方法吧。说我们添加获取名称将显示在用户的便捷方法:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
@JsonIgnore
public String getDisplayName() {
return getName() + “ (" + getHandle() + ")";
}
@Override
public String toString() {
return "User{handle='" + handle + "\', name='" + name + "\', displayName='" + getDisplayName() + "'}";
}
}
现在让我们阅读火力地堡的用户,并将其写回一个新的位置:
Firebase srcRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
final Firebase copyRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/copiedusers");
srcRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
copyRef.child(userSnapshot.getKey()).setValue(user);
}
}
@Override
public void onCancelled(FirebaseError firebaseError) { }
});
的JSON在在copiedusers
节点如下:
"copiedusers": {
"-Jx5vuRqItEF-7kAgVWy": {
"displayName": "Frank van Puffelen (puf)",
"handle": "puf",
"name": "Frank van Puffelen"
},
"-Jx5w3IOHD2kRFFgkMbh": {
"displayName": "Kato Wulf (kato)",
"handle": "kato",
"name": "Kato Wulf"
},
"-Jx5x1VWs08Zc5S-0U4p": {
"displayName": "Jenny Tong (mimming)",
"handle": "mimming",
"name": "Jenny Tong"
}
}
这是不一样的源JSON,因为杰克逊识别新getDisplayName()
方法作为JavaB ean getter,从而将displayName
属性添加到它输出的JSON。我们通过将JsonIgnore
注释添加到getDisplayName()
来解决此问题。
@JsonIgnore
public String getDisplayName() {
return getName() + "(" + getHandle() + ")";
}
当序列化用户对象,杰克逊现在忽略getDisplayName()
方法和JSON,我们写出来的将是相同的是我们得到了它。
您如何看待这种方法? stackoverflow.com/a/36706248/2819864 – RominaV