3

I have nested objects in Firestore where I have the document tied to the logged in user's UUID.

I am able to get the nested values out by converting to a Map and calling getData on the DocumentSnapshot. Then looping over the Map entry set. I have typically used Firestore's methods to convert the result back over to my custom object (e.g. documentSnapshot.toObject(POJO.class) and throw them in a list, but since I am getting the nested values as a Map, will I need to use something like Jackson or GSON? Once this loop is done, I want to convert to POJO and add each to the arraylist, in this case allVehices.

public ArrayList<Vehicle> getAllVehicles() {
    FirebaseFirestore.getInstance().collection("vehicles")
            //.whereEqualTo("vehicleUUID",FirebaseAuth.getInstance().getCurrentUser().getUid())
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (DocumentSnapshot documentSnapshot : task.getResult()) {
                            Map<String,Object> map = (Map<String,Object>) documentSnapshot.getData();
                            for (Map.Entry<String,Object> entry : map.entrySet()) {
                                System.out.print(entry.getKey() + "/" + entry.getValue());

                            }
                        }
                    }
                }
            });

    return allVehicles;

}

Firestore structure

3 Answers 3

1

Yes, you will have to find your own solution to this one, as the Firestore SDK doesn't currently support mapping individual fields into Java objects. It only works with the entire contents of the document right now.

Feel free to file a feature request if you would like the SDK to provide a way to do this mapping for you.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah that's what I was starting to think...so in this case, using something like GSON to handle it would be my best bet?
Sorry, I don't really know GSON well enough to know if it can do what you want.
1

GSON can work as a workaround for documents that contain maps that you would like to have each as their own individual object. So if your mapping individual fields into Java objects the below code is a workaround for SDK limitations, but will have worse performance than the SDK or Jackson.

public ArrayList<Vehicle> getAllVehicles() {
    FirebaseFirestore.getInstance().collection("vehicles")
            //.whereEqualTo("vehicleUUID",FirebaseAuth.getInstance().getCurrentUser().getUid())
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (DocumentSnapshot documentSnapshot : task.getResult()) {
                            Map<String,Object> map = (Map<String,Object>) documentSnapshot.getData();
                            for (Map.Entry<String,Object> entry : map.entrySet()) { 
                                Gson gson = new Gson();
                                JsonElement jsonElement = gson.toJsonTree(entry.getValue());
                                MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);
                                pojo.setKeyName(entry.getKey());

                            }
                        }
                    }
                }
            });

    return allVehicles;

}

Comments

0

It appears this feature was added in version 18.0.0 which released shortly before this question was asked. The Firestore Android API supports mapping nested object fields to and from their respective classes.

Parent.java

public class Parent {
  private Child child;

  public Parent() {
    this(null);
  }

  public Parent(Child child) {
    this.child = child;
  }

  public Child getChild() {
    return child;
  }
}

Child.java

public class Child {
  private String value;

  public Child () {
    this(null);
  }

  public Parent(String value) {
    this.value = value;
  }

  public String getValue() {
    return value;
  }
}

Repository.java

// Store Parent:
firestore.collection("collection")
    .document("id1")
    .set(myParent);  // Add appropriate listeners
// Retrieve Parent:
client.collection("collection")
    .document("id1")
    .get()
    // The returned Parent instance will have the child field set.
    .addOnSuccessListener(snapshot -> snapshot.toObject(Parent.class);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.