1
votes

Attendu une liste lors de la désérialisation, mais a obtenu une classe java.util.HashMap

J'essaie d'obtenir une liste d'utilisateurs de Firebase, sous Android.

entrez la description de l'image ici

J'ai déjà l'uuid de l'utilisateur, et en utilisant cela, j'essaye d'obtenir l'objet entier. L'uuid est à la fois le nom du nœud et un champ à l'intérieur du nœud utilisateur (identique, bien sûr).

Voici mon code:

public class User {

private String uuid;
private String email;
private String name;
private List<User> friends;
private List<Animal> animals;

public User() {
}

public User(String email, String name) {
    this.email = email;
    this.name = name;
}

public User(String uuid, String email, String name) {
    this.uuid = uuid;
    this.email = email;
    this.name = name;
}
... // getters and setters, toString and other such
}

Je ne savoir si l'erreur "Liste attendue mais HashMap" provient de l'intégralité du DataSnapshot lui-même, ou de la liste des animaux à l'intérieur de l'utilisateur (La classe utilisateur a un champ Liste des animaux)

J'ai déjà vérifié ceci question similaire Andorid- Attendu une liste lors de la désérialisation, mais a obtenu une classe java.util.HashMap et plusieurs autres mais je ne comprends toujours pas ce qui ne va pas.

EDIT: J'essaye de récupérer l'e-mail de l'utilisateur, sachant que c'est son ID (uuid). Bien qu'il ne soit pas nécessaire d'obtenir l'intégralité de l'objet User, je suis curieux de savoir comment cela serait fait, car je ne parviens pas à faire l'un ou l'autre.

EDIT: voici ma classe User

DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
Query query = usersRef.orderByChild("uuid").equalTo(animalMarker.getUserUid());
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Log.d(TAG, "onDataChange: xxxxxxxx---- entered onDataChange");

            // go to node "users/userUID" , becuase dataSnapshot is parent node
            for (DataSnapshot ds : dataSnapshot.getChildren()) {
                Log.d(TAG, "xxxxxxxx---- onDataChange: ds= " + ds);
                User user = ds.getValue(User.class);
                Log.d(TAG, "xxxxxxxx---- onDataChange: user=" + user);
                // createdByTV.setText("Created by \n" + user.getEmail());
            }

        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });

Lorsque vous essayez d'obtenir l'utilisateur qui n'a pas le nœud animaux à l'intérieur, tout fonctionne bien. mais lorsque vous essayez d'obtenir l'utilisateur avec le nœud animaux à l'intérieur, l'application se bloque.


2 commentaires

Pouvez-vous nous montrer votre classe User ?


J'ai mis à jour la question avec la classe User


3 Réponses :


0
votes

La liste des animaux n'est pas à l'intérieur de l'utilisateur, elle est à l'intérieur du nœud des utilisateurs. Dans tous les cas, le rendre interne à l'objet utilisateur semble être plus imbriqué que nécessaire. Vous devriez avoir un autre nœud pour les animaux

usersRef.child(uid).addSingleEvent..

...onDataChange...
User user = datasnapshot.getValue(User.class);

Votre problème maintenant est que vous faites une requête au lieu d'obtenir la valeur du nœud

user_animals:{
    uid:{key1:{}, key2:{}
}

Vous besoin de créer une classe User qui reflète les attributs de vos utilisateurs dans le RTD


5 commentaires

J'ai. En utilisant le premier utilisateur qui n'a pas d'animaux à l'intérieur, l'application fonctionne bien. Cependant, lors de la récupération de l'autre utilisateur, l'application s'est plantée. Les listes à l'intérieur de la classe User doivent-elles être des HashMaps pour que cela fonctionne? J'avais l'impression que Firebase Realtime Database pouvait récupérer l'objet personnalisé (Animal) à partir d'un autre objet (User).


Les animaux ne sont pas à l'intérieur de l'utilisateur mais à l'intérieur du nœud utilisateurs


Je suis désolé mais je ne comprends toujours pas. Ce nœud (nommé "animaux" à l'intérieur de l'utilisateur) ne serait-il pas une liste, chaque nœud à l'intérieur étant un élément de cette liste?


Vos animaux ne sont pas à l'intérieur d'un seul utilisateur mais à l'intérieur des utilisateurs, vos données sont 1 utilisateur et 1 liste d'animaux


Désolé, je pense que je ne comprends pas bien. Mais mon nœud "animaux" est à l'intérieur d'un utilisateur, et chaque utilisateur peut en avoir un (liste). N'est-ce pas la même chose que l'utilisateur de la classe? La logique étant que tous les animaux de la liste d'un utilisateur appartiennent à cet utilisateur.



4
votes

En fait, j'ai répondu à cette question mais dans ce cas, le problème est un peu différent. Vous obtenez donc l'erreur suivante:

Liste attendue mais a obtenu HashMap

Parce que votre nœud animaux qui existe dans chaque objet utilisateur n'est pas une liste d'objets animaux est en fait une carte d'objets animaux et c'est pourquoi cette erreur .

Bien qu'il ne soit pas nécessaire d'obtenir l'intégralité de l'objet User, je suis curieux de savoir comment cela serait fait, car je ne parviens pas à faire l'un ou l'autre de ces éléments.

C'est vrai, vous pouvez obtenir l'adresse e-mail simplement en utilisant la ligne de code suivante:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference animalsRef = rootRef.child("users").child(uid).child("animals");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<Animal> animalList = new ArrayList<>();
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            Animal animal = ds.getValue(Animal.class);
            animalList.add(animal);
        }

        //Do what you need to do with the animalList
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
animalsRef.addListenerForSingleValueEvent(valueEventListener);

Maintenant, pour mapper un DataSnapshot code> à un Utilisateur et obtenir une liste d'objets animaux d'un utilisateur particulier, veuillez supprimer:

//private List<User> friends;
//private List<Animal> animals;

Et utiliser les lignes de code suivantes :

String email = ds.child("email").getValue(String.class);


1 commentaires

Rebonjour! Et merci beaucoup pour votre réponse, cela a fonctionné! En fin de compte, j'ai changé les données de l'objet utilisateur d'une liste à un HashMap comme solution de contournement. Je ne voulais pas créer un autre DatabaseReference et ValueEventListener, mais à la place récupérer l'objet User entier avec ses animaux. Votre réponse m'a donné plus d'informations sur l'utilisation de Firebase Database, merci.



0
votes

La façon dont vous construisez votre arbre est la racine du problème.

J'ai eu la même erreur aujourd'hui lors de la refactorisation de l'arborescence Firebase d'un ancien projet.J'ai donc cherché l'erreur dans google et j'ai trouvé cette page, et j'ai remarqué ces 3 attributs utilisateur à l'intérieur de votre nœud animal qui semblaient déplacés.

Je suis donc retourné à mon arbre et j'avais ajouté par erreur une paire clé: valeur dans l'un de mes nœuds de liste, alors je les ai supprimés et tout allait bien.

Le problème:

C'est parce que vous avez une liste d'animaux et à l'intérieur de cette liste vous avez ces 3 valeurs-clés (email, uuid, nom), cela confond la sérialisation de Firebase donc il essaie de la convertir en hashmap

La solution:

Je pense que vous en bénéficierez à l'avenir si vous ne le contournez pas et procédez comme suit: les 3 attributs utilisateur email, name et uuid doivent être enveloppés dans un nœud différent à l'intérieur de l'utilisateur tree, quelque chose comme user_data et vous devriez avoir un nœud différent pour les animaux qui n'auront que la liste des animaux!

  • utilisateurs
    • sfdasfasfasfasf
      • données_utilisateur
        • e-mail: "asdf"
        • nom: "asdfas"
        • uuid: "dfqwtr4"
      • animaux
        • asdfaskdfjlasdgafd
          • adulte: "asdf"
          • animalId: "asdfas"
          • animalName: "dfqwtr
          • approxAge: "asdf"
          • neutred: "asdfas"
          • photoLink: "dfqwtr"
        • sdafasfdasgasga
          • adulte: "asdf"
          • animalId: "asdfas"
          • animalName: "dfqwtr
          • approxAge: "asdf"
          • neutred: "asdfas"
          • photoLink: "dfqwtr"

Ensuite, votre pojo devrait ressembler à quelque chose comme: une classe User avec les propriétés d'un UserData et de List avec les noms correspondants pour sérilisation.


0 commentaires