1

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");
beastlyCoder
  • 2,349
  • 4
  • 25
  • 52
  • As you can see from the log you posted, the error is due to the fact that you are getting string type data from json and you are assigning it to you DJProfile object. You have to parse you json data and convert it into DJProfile type. – Umair May 08 '19 at 03:53
  • do you have any idea on how to do that? I don't know where/how to put that data in – beastlyCoder May 08 '19 at 03:54
  • Implement it where you are getting allDeeJays. Parse it like below link does and then I should work. you have to take a look at this: https://stackoverflow.com/questions/20194124/how-to-convert-json-string-to-custom-object – Umair May 08 '19 at 03:57

2 Answers2

1

Change your database the following:

allDeeJays
     PushId
       djName         : "john"
       googleUserName : "john"

Then you would be able to map your POJO with the database.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • I updated my question as to what the JSON looks like now – beastlyCoder May 08 '19 at 04:24
  • please use the json i gave you in this answer, because in your POJO class you have the following variables`String djName; String googleUserName;` so to be able to map them you need the same variable name in the database. – Peter Haddad May 08 '19 at 05:24
  • I have fixed my database accordingly, the error is gone, but now my query doesn't return anything – beastlyCoder May 08 '19 at 15:54
1

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.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I have restructed my database as you've suggested, and modified the recyclerview accordingly, but now I am not getting any results from my query. Is my original code for querying sufficient for the information I'm trying to receive? – beastlyCoder May 08 '19 at 15:52
  • It also says that DataSnapshot is missing a default constructor – beastlyCoder May 08 '19 at 16:25
  • Your new JSON uses `name` as the property name, while the `DjProfile` class has a `djName` property. Since those names are not the same, Firebase won't be able to map them. You can most easily see the JSON that your class expects by **writing** an instance of it to the database and checking the result. – Frank van Puffelen May 08 '19 at 16:26
  • Please go easy on the number of comments. It's hard to respond to multiple comments each time. I just added a sample of a `SnapshotParser` and a link to the documentation of that. – Frank van Puffelen May 08 '19 at 16:35
  • Yeah, I deleted them sorry. Didn't see the edit until now – beastlyCoder May 08 '19 at 16:35
  • I think my issue now is just the querying of the data. I am no longer getting errors on the DataSnapshot – beastlyCoder May 08 '19 at 16:44
  • I added an example of how to query on child property values. – Frank van Puffelen May 09 '19 at 00:55