IT

JSON을 Firebase에서 Java 개체로 전환할 때 "유형으로 바운스하지 못했습니다"가 표시되는 이유는 무엇입니까?

itgroup 2023. 7. 2. 19:15
반응형

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 {
  ...
}

코드를 , 이 무시할 수 될 입니다.stackIdJSON에서 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 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 간의 기본 매핑을 사용하는 것이 가장 좋습니다.그렇지만@PropertyNameJava 클래스에 매핑할 수 없는 기존 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

반응형