-1

I'm creating one document with this data:

{
   "fields":{
      "meta":{
         "mapValue":{
            "fields":{
               "semana":{
                  "stringValue":"Semana XX"
               },
               "fecha":{
                  "stringValue":"20191209"
               },
               "titulo":{
                  "stringValue":"Lunes II de Adviento"
               },
               "mensaje":{
                  "stringValue":""
               },
               "tiempo":{
                  "integerValue":1
               }
            }
         }
      },
      "lh":{
         "mapValue":{
            "fields":{
               "0":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/0/0108022"
               },"1":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/1/0108022"
               },"2":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/2/0100022"
               },"3":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/3/0100022"
               },"4":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/4/0100022"
               },"5":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/5/0100022"
               },"6":{
                  "referenceValue":"projects/miproject/databases/(default)/documents/es/v1/liturgia/lh/6/0100022"
               }
            }
         }
      }
   }
}

The document is created without a problem.

Now, in Android, I need to fill two types of objects:

a. With the key meta I need to populate one object of type MetaLiturgia, and

b. I take one of the references to populate another object.

My problem is in a, I can't populate the MetaLiturgia object.

Code

    DocumentReference calRef = db.collection(CALENDAR_PATH).document(fechaYY).collection(fechaMM).document(fechaDD);
    calRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
        @Override
        public void onEvent(@Nullable DocumentSnapshot calSnapshot,
                            @Nullable FirebaseFirestoreException e) {
            if (calSnapshot != null && calSnapshot.exists()) {
                Log.d(TAG,calSnapshot.toString());
                Log.d("meta",calSnapshot.get("meta").toString());
                /* (a) Error here, line 120 is below line*/
                mMeta = (MetaLiturgia) calSnapshot.getData();
                DocumentReference dataRef=calSnapshot.getDocumentReference("lh.1");
                if (e != null || dataRef==null) {
                    launchVolley();
                    return;
                }
                dataRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot dataSnapshot) {
                        /*(b) No problem here*/
                        mBreviario = dataSnapshot.toObject(Breviario.class);
                        showData();
                    }
                });
            } else {
                launchVolley();
            }
        }
    });

I can see the data in the Log:

D/meta: {fecha=20191209, tiempo=1, semana=Semana XX, titulo=Lunes II de Adviento, mensaje=}

But I'm having this error:

2019-12-09 10:44:52.233 25121-25121/org.my.app E/AndroidRuntime: FATAL EXCEPTION: main Process: org.my.app, PID: 25121 java.lang.ClassCastException: java.util.HashMap cannot be cast to org.my.app.model.MetaLiturgia at org.my.app.activities.OficioActivity$1.onEvent(OficioActivity.java:120)

How I can do this?

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
A. Cedano
  • 557
  • 7
  • 39
  • At which line of code are you getting that error? – Alex Mamo Dec 09 '19 at 12:32
  • @AlexMamo at this line: `mMeta = (MetaLiturgia) calSnapshot.getData();` – A. Cedano Dec 09 '19 at 12:44
  • I cannot see that line of code in the code you have shared. – Alex Mamo Dec 09 '19 at 12:45
  • @AlexMamo it's is after this comment: `/* (a) Error here, line 120 is below line*/` – A. Cedano Dec 09 '19 at 12:57
  • Can you also please indicate the values of `CALENDAR_PATH`, `fechaYY`, `fechaMM` and `fechaDD`? – Alex Mamo Dec 09 '19 at 13:00
  • @AlexMamo these values are the path to the final document. It's not problem with that. I you read the question you can see that the path is right because I'm having the data, but **I can't fill one object with part of this data**, this is the problem. The Log show the values of key `meta`: **`meta: {fecha=20191209, tiempo=1, semana=Semana XX, titulo=Lunes II de Adviento, mensaje=}`** then the path is right. – A. Cedano Dec 09 '19 at 13:03
  • Why not use `mMeta = calSnapshot.toObject(MetaLiturgia.class);`? Alternatively, add a static method to MetaLiturgia called `fromHashMap(HashMap map)` that constructs your MetaLiturgia class using the values of map and returns the new instance. – samthecodingman Dec 09 '19 at 13:53
  • @samthecodingman only doing `mMeta = calSnapshot.toObject(MetaLiturgia.class);` is not working, I have serialization error. I tryed with Gson and it's working: `Gson gson = new Gson(); JsonElement jsonElement = gson.toJsonTree(meta); mMeta = gson.fromJson(jsonElement, MetaLiturgia.class);` Now is working with Gson, but I want to know if it's possible to do it only with Firestore methods. – A. Cedano Dec 09 '19 at 14:30
  • Can you add your `MetaLiturgia class` to the question? It might give us some insight to how `Gson` is handling it. – samthecodingman Dec 10 '19 at 04:45

1 Answers1

2

You are getting the following exception:

E/AndroidRuntime: FATAL EXCEPTION: main Process: org.my.app, PID: 25121 java.lang.ClassCastException: java.util.HashMap cannot be cast to org.my.app.model.MetaLiturgia

When using the following line of code:

mMeta = (MetaLiturgia) calSnapshot.getData();

Because when you are calling calSnapshot.getData() the type of object that is returned is a HashMap and not a MetaLiturgia and there is no way in Java you can cast an object of type HashMap to MetaLiturgia. Since that object is a HashMap, you should get it accordingly. But please also note that your fields property is a HashMap of HashMaps. So you should iterate twice in order to get the desired data.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Then I think i'm having one problem of design. I will try to create one object that have `meta` and `lh` properties, map the snapshoot to this object and use this object for get the reference I need in the part (b) of my code. – A. Cedano Dec 09 '19 at 17:14
  • The simplest solution might be to create that object that you say and save all of them in a subcollection. In the end, simply iterate through the collection and get all objects and then convert them to the desired class. – Alex Mamo Dec 09 '19 at 17:17
  • Alex I created that object with two properties for `meta` and `lh`, but I can't to do: **`mLiturgia = calSnapshot.toObject(Liturgia.class);`**, i'm having error: *`Could not deserialize object. Class java.util.HashMap has generic type parameters, please use GenericTypeIndicator instead (found in field 'meta')`* – A. Cedano Dec 09 '19 at 17:58
  • That's a very know issue. Check [this](https://stackoverflow.com/questions/37688031/class-java-util-map-has-generic-type-parameters-please-use-generictypeindicator) out. – Alex Mamo Dec 09 '19 at 18:01
  • Alex I can get the data into a `Map` doing this: `Map map = (Map) calSnapshot.getData();` but I don't know how to fill my object (`Liturgia`) with this info. I try too [the point `5` of this response](https://github.com/firebase/firebase-android-sdk/issues/222#issuecomment-459898431) without success. In this case I can see *`[CustomClassMapper]: No setter/field for fecha found on class ...`* then the method suggested try to populate the class, but key by key, I need to populate as objects of type `meta` and `lh`. – A. Cedano Dec 09 '19 at 18:55
  • There is no way you can directly get `Liturgia` objects while iterating through the map. You should iterate, get the data and only then create `Liturgia` objects. You cannot map `Liturgia` objects directly. You usually get `[CustomClassMapper]: No setter/field for fecha found on class` when you have fields that exist, but don't have the corresponding getters and setters or are not public. – Alex Mamo Dec 09 '19 at 19:01
  • Alex I finally used GSon for populate the `Liturgia` object with each part of data. I don't find one way to do that with Firestore methods :-(. – A. Cedano Dec 09 '19 at 19:32
  • That's fine too. It's just another approach. So as long as you solved that problem, you can go ahead with other parts of your project. – Alex Mamo Dec 10 '19 at 07:16