2

My Database:

    {
    "Shops": {
        "Title": {
            "1": "Footlocker",
            "2": "Nike Store",
            "3": "Adidas Store"
        },
        "Lat": {
            "1": "123",
            "2": "123",
            "3": "123"
        },
        "Lon": {
            "1": "123",
            "2": "123",
            "3": "123"
        }
    }
}

The numbers "1","2" and "3" represent a shop. For example "1" shop has "Footlocker" for title and "123" latitude (probably this should be a number, but that's not my problem).

My goal is to get all the titles in a Hashmap<String,String> (key would be "1"... value "Footlocker" etc...)

So I create a reference to "Title" key in database and add the listener,

DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Shops").child("Title");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                HashMap<String,String> map = (HashMap<String,String>) dataSnapshot.getValue();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

As you can imagine the above code throws an exception because an ArrayList cannot be cast to a HashMap.

My question is, shouldn't I be getting a HashMap instead with the numbers as keys and the titles as values?

AL.
  • 36,815
  • 10
  • 142
  • 281
Mr T
  • 506
  • 2
  • 9
  • 26
  • Your keys look more like indices in a list than keys for a map – OneCricketeer Feb 22 '17 at 13:39
  • @cricket_007 I know it's not a proper value for a key, but even "1" is a String key. Let's not focus there, the problem is elsewhere – Mr T Feb 22 '17 at 13:40
  • I'm just asking why you think it should be a map... Your firebase database lists the elements linearly, right? By index positioning. – OneCricketeer Feb 22 '17 at 13:42
  • @cricket_007 Well I thought if I had an array in JSON then that would have returned a list, because it doesnt contain any keys in it... for example { "Shop":["FootLocker","Nike","Adidas"] } Am I right? – Mr T Feb 22 '17 at 13:47
  • That is a list, yes. Firebase isn't a direct mapping to JSON, though – OneCricketeer Feb 22 '17 at 13:49
  • What? Really? I read at the documentation that "It's a JSON tree", so I studied a little bit of JSON before going through... – Mr T Feb 22 '17 at 13:51
  • 1
    It's "similar", (and behind the scenes stored in JSON), but the Firebase dashboard somewhat destroys the "structure" of valid JSON... Anyway, I don't know why you even want a map. You have a list of stores with the order preserved. A Hashmap has no order and you'll have to check if keys existed to get data you wanted – OneCricketeer Feb 22 '17 at 13:55
  • @cricket_007 Thanks for the effort! – Mr T Feb 22 '17 at 14:00

1 Answers1

4

You've shown your "database" as a JSON document.

If you parsed that using a JSON parser, sure, you might expect a TreeMap, to be exact, but in Firebase's terms, I think you've confused the "index" of the elements with what you think should be a "key".

So, you get a list, not a Map. No big deal, really. You can still iterate over the elements

If you want a (somewhat) better structure, I would suggest

Stores 
    Footlocker
        Lat
        Lon
    Nike
       ... 
    Adidas
       ... 

Or as Frank comments, use the natural key ordering that Firebase can generate.

Stores 
    <id_0>
        name: "Footlocker"
        Lat: 0.00
        Lon: 0.00
    <id_1>
        name: "Nike"
        ...
    <id_2> 
        name: "Adidas"
        ... 

Additional point. Don't use a HashMap, use objects to represent the data

public class Store {
    String name;
    Double lat, lon;

    public Store() {
        // Required empty-constructor
    }

    // getters & setters...
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Thanks. Can you share any good source for building a better structure for a json database? – Mr T Feb 22 '17 at 14:17
  • Not really... Just takes practice and depends entirely on the queries you want to run – OneCricketeer Feb 22 '17 at 14:18
  • 3
    Good answer! To the data modeling comment: If the items have a natural key, use that natural key to store them under. So when you're storing a list of users, store them under their UID. If your shops don't have a natural key yet, consider generating one that is not susceptible to this problem. The Firebase documentation uses the `push()` method to generate such IDs. But in the very unlikely case that your keys *must* use sequential numeric values, prefix them with a string to prevent Firebase's array coercion. E.g. `store1`, `store2`, `store3`. – Frank van Puffelen Feb 22 '17 at 15:18
  • 1
    @Skemelio Use the structure that minimizes data redundancy , can be modelled as model class and easier to query on . – Rishabh Maurya Feb 22 '17 at 15:53
  • @FrankvanPuffelen That's what I was aiming about with the numbers. To store their UID! – Mr T Feb 22 '17 at 15:55
  • @RishabhMaurya You mean to store them directly as objects so I can get them easily? – Mr T Feb 22 '17 at 15:57
  • 1
    @RishabhMaurya Data redundancy is acceptable in NoSQL solutions where JOINs are costly / non-existant – OneCricketeer Feb 22 '17 at 15:57
  • @Skemelio Yeah like cricket_007 has mentioned in the answer .Then you will able to retrieve the data directly in ArrayList . – Rishabh Maurya Feb 22 '17 at 16:05