Search code examples
androidfirebasefirebase-realtime-databasefirebaseui

Cannot convert String to DjProfile(firebase)


I am trying to get the data from my json to display through a firebase recyclerview but I am running into this error:

com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.android.heydj.DjProfile
    at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@16.0.6:423)
    at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@16.0.6:214)
    at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@16.0.6:79)
    at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@16.0.6:212)
    at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:29)
    at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:15)
    at com.firebase.ui.common.BaseCachingSnapshotParser.parseSnapshot(BaseCachingSnapshotParser.java:35)
    at com.firebase.ui.common.BaseObservableSnapshotArray.get(BaseObservableSnapshotArray.java:52)
    at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:106)
    at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:122)

My Json:

 "allDeeJays" : {
    "-Le5FguoZsnT2lejgAkZ" : "yousucks",
    "-Le5IsCPK69NTbgbgUUo" : "ffffggg",
    "-Le5J5CmPkddSaK_MgpG" : "ahhhaahhaahha"
  }

My DjProfile class is defined as follows:

public class DjProfile
{
    String djName;
    String googleUserName;

    public DjProfile(String djName, String googleUserName)
    {
        this.djName = djName;
        this.googleUserName = googleUserName;
    }
    public DjProfile(){}

    public void setdjName(String djName)
    {
        this.djName = djName;
    }

    public String getdjName()
    {
        return djName;
    }
}

My firebase recyclerview is as follows:

query = mProfileDatabase.child("allDeeJays")
        .orderByValue()
        .startAt(t.getText().toString()).endAt(t.getText().toString() + "\uf8ff");

FirebaseRecyclerOptions<DjProfile> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<DjProfile>()
        .setQuery(query, DjProfile.class)
        .build();


firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<DjProfile, ResultsViewHolder>(firebaseRecyclerOptions)
{

    @NonNull
    @Override
    public ResultsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.searchitem_list, viewGroup, false);
        return new ResultsViewHolder(view);
    }

    @Override
    protected void onBindViewHolder(@NonNull ResultsViewHolder holder, final int position, @NonNull final DjProfile model) {
        holder.setDjProfile(model);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(getApplication(), AddSongRequest.class);
                i.putExtra("DjName", model.getdjName());
                startActivity(i);
            }
        });
    }
};
firebaseRecyclerAdapter.startListening();

ViewHolder class for firebase recyclerview:

public static class ResultsViewHolder extends RecyclerView.ViewHolder
{
    private TextView djNameView;

    public ResultsViewHolder(View itemView)
    {
        super(itemView);
        djNameView = itemView.findViewById(R.id.result_dj);
    }

    void setDjProfile(DjProfile profile)
    {
        String djName = profile.getdjName();
        profile.setdjName(djName);
    }
}

Any help is appreciated :)

EDIT My JSON is now formatted as:

  "allDeeJays" : {
    "-LeNGZKDoIcVOLUokvrP" : {
      "djName" : "ahhahaha"
    },
    "-LeNGb2sy9qG_U0zA1xS" : {
      "djName" : "newdj"
    }
  }

And now I can't display the values of name into the recyclerview using the following:

            query = mProfileDatabase.child("allDeeJays")
                    .orderByValue()
                    .startAt(t.getText().toString()).endAt(t.getText().toString() + "\uf8ff");

Solution

  • Your DjProfile class defines a JSON structure that looks like this:

    {
        djName: "Name of DJ"
    }
    

    So a list of these DJs would look like this:

    "allDeeJays" : {
      "-Le5FguoZsnT2lejgAkZ" : { "djName": "..." },
      "-Le5IsCPK69NTbgbgUUo" : { "djName": "ffffggg" },
      "-Le5J5CmPkddSaK_MgpG" : { "djName": "ahhhaahhaahha" }
    }
    

    You would query the above structure with:

    query = mProfileDatabase.child("allDeeJays")
                    .orderByChild("djName")
                    .startAt("f").endAt("f\uf8ff")
    

    Since your JSON looks different, Firebase won't be able to convert it, which is why you're getting an exception.

    You can either change your JSON to match your code, which is what Peter answered, or you can change your code to match the JSON.

    To do the latter with FirebaseUI means that you won't tell FirebaseUI to use your custom class anymore, but it will have to work with the raw snapshots. The code will look something like this:

    FirebaseRecyclerOptions<DataSnapshot> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<DataSnapshot>()
            .setQuery(query, new SnapshotParser<DataSnapshot>() {
                @Override
                public DataSnapshot parseSnapshot(DataSnapshot snapshot) {
                    return snapshot;
                }
            }).build();
    
    firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<DataSnapshot, ResultsViewHolder>(firebaseRecyclerOptions)
    {
    
        @NonNull
        @Override
        public ResultsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.searchitem_list, viewGroup, false);
            return new ResultsViewHolder(view);
        }
    
        @Override
        protected void onBindViewHolder(@NonNull ResultsViewHolder holder, final int position, @NonNull final DataSnapshot snapshot) {
            // Here you convert the DataSnapshot to whatever data your ViewHolder needs
            DjProfile model = new DjProfile(snapshot.getKey(), snapshot.getValue(String.class));
    
            holder.setDjProfile(model);
            ...
        }
    };
    

    The new snapshot parser in here is based on this comment:

    Also see the documentation of FirebaseUI on SnapshotParser.