JSON을 Firebase에서 Java 개체로 전환할 때 "유형으로 바운스하지 못했습니다"가 표시되는 이유는 무엇입니까?
[공개:저는 파이어베이스의 엔지니어입니다.이 질문은 한 번에 많은 질문에 답하기 위한 참조 질문입니다.]
Firebase 데이터베이스에 다음과 같은 JSON 구조가 있습니다.
{
"users": {
"-Jx5vuRqItEF-7kAgVWy": {
"handle": "puf",
"name": "Frank van Puffelen",
"soId": 209103
},
"-Jx5w3IOHD2kRFFgkMbh": {
"handle": "kato",
"name": "Kato Wulf",
"soId": 394010
},
"-Jx5x1VWs08Zc5S-0U4p": {
"handle": "mimming",
"name": "Jenny Tong",
"soId": 839465
}
}
}
나는 다음 코드로 이것을 읽고 있습니다.
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
}
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) { }
});
하지만 다음과 같은 오류가 발생합니다.
"FirebaseEventTarget" com.firebase.client 스레드에서 예외가 발생했습니다.파이어베이스예외:유형으로 바운스하지 못했습니다.
사용자를 Java 개체로 읽으려면 어떻게 해야 합니까?
Firebase는 Jackson을 사용하여 Java 객체를 JSON으로 직렬화하고 JSON을 Java 객체로 역직렬화할 수 있습니다.잭슨에 대한 자세한 내용은 잭슨 웹 사이트와 잭슨 주석에 대한 이 페이지에서 확인할 수 있습니다.
이 답변의 나머지 부분에서는 잭슨을 Firebase와 함께 사용하는 몇 가지 일반적인 방법을 보여드리겠습니다.
전체 사용자 로드 중
Firebase에서 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) { }
});
사용자 클래스는 JavaBean 속성 패턴을 따를 수 있습니다.모든 JSON 속성은 User 클래스의 필드별로 매핑되며 각 필드에 대한 공개 getter 메서드가 있습니다.모든 속성이 동일한 이름으로 매핑되도록 함으로써 잭슨이 자동으로 매핑할 수 있습니다.
또한 Jackson 주석을 Java 클래스와 해당 필드 및 메서드에 배치하여 매핑을 수동으로 제어할 수 있습니다.는 가장 인 두의 주석 (가장다반하두주대가니습설겠명해에석지인일적▁(ations가)을 다룰 @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을 사용자 개체로 역직렬화할 수 없음을 나타냅니다.중첩된 예외에서 다음과 같은 이유를 알 수 있습니다.
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: java.io.StringReader@43079089; 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에서 JSON을 삭제합니다.도 JSON에 때 수 .User
명령어:
@JsonIgnoreProperties({ "stackId" })
private static class User {
...
}
코드를 , 이 무시할 수 될 입니다.stackId
JSON에서 JSON을 다시 사용자 개체로 역직렬화할 수 있습니다.
JSON에 속성을 추가하는 것은 Firebase 응용 프로그램에서 매우 일반적이기 때문에, Jackson에게 Java 클래스에 매핑이 없는 모든 속성을 무시하라고 말하는 것이 더 편리할 수 있습니다.
@JsonIgnoreProperties(ignoreUnknown=true)
private static class User {
...
}
수 있습니다.User
사용자 개체에는 JSON에 있었던 모든 정보가 포함되어 있지 않으므로 Firebase에 다시 쓸 때 주의해야 합니다.
부분적으로 사용자 저장
사용자 정의 자바 클래스가 좋은 이유 중 하나는 편리한 방법을 추가할 수 있기 때문입니다.사용자에게 표시할 이름을 가져오는 편리한 방법을 추가한다고 가정합니다.
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의 사용자를 읽고 새 위치에 다시 기록해 보겠습니다.
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) { }
});
인더더에 .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과 잭슨은 "JSON"을 입니다. 잭슨이 새로운 것을 인식하기 때문입니다.getDisplayName()
하여 자빈게터그따추라다습니었가되서리고방바로서의법▁a▁method▁as다니습▁thus었추▁added되▁java▁a가bean자따바.displayName
출력하는 JSON에 대한 속성입니다.우리는 이 문제를 다음과 같이 추가함으로써 해결합니다.JsonIgnore
에대주석에 대한 .getDisplayName()
.
@JsonIgnore
public String getDisplayName() {
return getName() + "(" + getHandle() + ")";
}
를 직렬화할 때 은 "" "" "" "" "" ""를 합니다.getDisplayName()
우리가 작성하는 방법과 JSON은 우리가 받은 것과 같을 것입니다.
Android/Java용 Firebase SDK 9.x 이상 버전에서는 JSON을 직렬화/비직렬화하기 위해 Jackson을 포함하지 않았습니다.대신 최신 SDK는 가장 일반적인 사용자 지정 요구사항을 제어하는 동시에 결과 JAR/APK 크기에 미치는 영향을 최소화하는 최소한의 사용자 지정 주석 세트를 제공합니다.
제 원래 답변은 다음과 같은 경우에도 유효합니다.
- Firebase 2.x SDK 사용
- Firebase 9.0 이상 SDK를 사용하지만 Java를 직렬화/직렬화하는 데 Jackson을 사용합니다. <->JSON
이 답변의 나머지 부분에서는 Firebase SDK 9.0 이상에서 직렬화/직렬화 시나리오를 처리하는 방법에 대해 설명합니다.
데이터 구조
먼저 Firebase 데이터베이스에서 JSON 구조를 살펴보겠습니다.
{
"-Jx86I5e8JBMZ9tH6W3Q" : {
"handle" : "puf",
"name" : "Frank van Puffelen",
"stackId" : 209103,
"stackOverflowId" : 209103
},
"-Jx86Ke_fk44EMl8hRnP" : {
"handle" : "mimming",
"name" : "Jenny Tong",
"stackId" : 839465
},
"-Jx86N4qeUNzThqlSMer" : {
"handle" : "kato",
"name" : "Kato Wulf",
"stackId" : 394010
}
}
전체 사용자 로드 중
가장 기본적으로 이 JSON의 각 사용자를 다음 Java 클래스에 로드할 수 있습니다.
private static class CompleteUser {
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+ "'}"; }
}
만약 우리가 그 분야들을 공개적으로 선언한다면, 우리는 심지어 게터도 필요하지 않습니다.
private static class CompleteUser {
public String handle;
public String name;
public long stackId;
}
사용자를 부분적으로 로드하는 중
사용자를 부분적으로 로드할 수도 있습니다. 예를 들어 다음과 같습니다.
private static class PartialUser {
String handle;
String name;
public String getHandle() {
return handle;
}
public String getName() { return name; }
@Override
public String toString() {
return "User{handle='" + handle + "', NAME='" + name + "''}";
}
}
이 클래스를 사용하여 동일한 JSON의 사용자를 로드하면 코드가 실행됩니다(다른 답변에 언급된 Jackson 변형과 달리).그러나 로깅 출력에 경고가 표시됩니다.
경고:클래스 주석 $PartialUser에서 stackId에 대한 설정자/필드를 찾을 수 없습니다.
그래서 그것을 없애고, 우리는 수업에 주석을 달 수 있습니다.@IgnoreExtraProperties
:
@IgnoreExtraProperties
private static class PartialUser {
String handle;
String name;
public String getHandle() {
return handle;
}
public String getName() { return name; }
@Override
public String toString() {
return "User{handle='" + handle + "', NAME='" + name + "''}";
}
}
부분적으로 사용자 저장
이전과 마찬가지로 계산된 속성을 사용자에게 추가할 수 있습니다.데이터를 데이터베이스에 다시 저장할 때 이러한 속성을 무시할 수 있습니다.이를 위해 속성/getter/setter/필드에 주석을 달 수 있습니다.@Exclude
:
private static class OvercompleteUser {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
@Exclude
public String getTag() { return getName() + " ("+getHandle()+")"; }
@Override
public String toString() { return "User{handle='"+handle+"', name='"+name+"', stackId="+stackId+ "'}"; }
}
이제 데이터베이스에 사용자를 쓸 때 값은getTag()
무시됩니다.
JSON에서 Java 코드와 다른 속성 이름 사용
또한 데이터베이스의 JSON에서 Java 코드의 필드/게터/세터 이름을 지정할 수 있습니다.방법: 필드/게터/세터에 주석 달기@PropertyName()
.
private static class UserWithRenamedProperty {
String handle;
String name;
@PropertyName("stackId")
long stackOverflowId;
public String getHandle() { return handle; }
public String getName() { return name; }
@PropertyName("stackId")
public long getStackOverflowId() { return stackOverflowId; }
@Override
public String toString() { return "User{handle='"+handle+"', name='"+name+"', stackId="+stackOverflowId+ "'}"; }
}
일반적으로 Firebase SDK에서 사용하는 Java <->JSON 간의 기본 매핑을 사용하는 것이 가장 좋습니다.그렇지만@PropertyName
Java 클래스에 매핑할 수 없는 기존 JSON 구조가 있는 경우 필요할 수 있습니다.
루트에 잘못된 쿼리 경로 폴더가 있기 때문입니다.이것은 예입니다.
My code:
private void GetUpdates(DataSnapshot snapshot){
romchat.clear();
for (DataSnapshot ds: snapshot.getChildren()){
Rowitemroom row = new Rowitemroom();
row.setCaption(ds.getValue(Rowitemroom.class).getCaption());
row.setFileUrl(ds.getValue(Rowitemroom.class).getFileUrl());
romchat.add(row);
/* Rowitemroom row = snapshot.getValue(Rowitemroom.class);
String caption = row.getCaption();
String url = row.getFileUrl();*/
}
if (romchat.size()>0){
adapter = new CustomRoom(context,romchat);
recyclerView.setAdapter(adapter);
}else {
Toast.makeText(context, "No data", Toast.LENGTH_SHORT).show();
}
}
db_url ="your apps`enter code here`.appspot.com/admins"
언급URL : https://stackoverflow.com/questions/32108969/why-do-i-get-failed-to-bounce-to-type-when-i-turn-json-from-firebase-into-java
'IT' 카테고리의 다른 글
vuej의 서버에서 데이터를 가져오는 방법은 무엇입니까? (0) | 2023.07.07 |
---|---|
PL/SQL에서 커서를 루프하는 FETCH/FOR 간의 차이 (0) | 2023.07.07 |
Oracle에서 Substor LIKE가 더 빠릅니까? (0) | 2023.07.02 |
DBMS_Scheduler.DROP_JOB(있는 경우에만 해당) (0) | 2023.07.02 |
치명적 오류 "안전하지 않은 저장소('/home/repon'은 다른 사용자 소유)" (0) | 2023.07.02 |