Get the value of a map field in cloud firestore - android

I have a code in getting the value of a map named Address.
Map<String, Object> map = document.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals("Address")) {
Log.i(TAG, entry.getValue().toString());
}
}
And here is the output
{Street=VP Inting Avenue, HouseNo=0186, Town=Tagbilaran City, Barangay=Poblacion I}
But I want to get the values (0186 VP Inting Avenue Poblacion I Tagbilaran City) only and not including their keys.

I think you're looking for:
Log.i(TAG, document.get("Address.HouseNo") + document.get("Address.Street") +
document.get("Address.Barangay") + document.get("Address.Town"));
If you know the exact path of the field, there is no need to loop over all fields. And with the . you can address nested fields.

Related

Getting 'unterminated object at' when trying to get value of certain key from JSON

Here's the json structure:
{userModel={name=Mark Kohl Mundi, photo_profile=***}, message=hi, timeStamp=1510326004316, newMsgIndicator=0}
Here's what I'm trying:
for (DataSnapshot childrenSnapshot: dataSnapshot.getChildren()) {
try {
JSONObject reader = new JSONObject(childrenSnapshot.getValue().toString());
String a = reader.getString("newMsgIndicator");
Log.d("A", String.valueOf(a));
} catch (JSONException e) {
e.printStackTrace();
}
}
Here's what I'm getting:
org.json.JSONException: Unterminated object at character 23 of {userModel={name=Mark Kohl Mundi, photo_profile=***}, message=hi, timeStamp=1510326004316, newMsgIndicator=0}
I know the error is because there is no double quotes ("") in the value of the keys.
What I want to know how can I insert double quotes in the json I'm getting.
You don't need to use JSONObject in order to get data from a Firebase database. Firebase database is structured as pair of key and value, which means that every node in the database is a Map. So instead of using JSONObject, i recomand you using this line of code:
Map<String, Object> map = (Map<String, Object>) childrenSnapshot.getValue();
Having this map, you can iterate now to get the data accordingly.
If your reference is pointing on a particular user object (node), to get the actual name, please use the following code:
String name = childrenSnapshot.child("name").getValue(String.class);

How to add child node under the existing Firebase json structure?

I am working on Android project, in which I saved details (email, password, name, mob, usertype, userid) while sign up, now I have to add extra details like long, lat and address to the existing structure for every user. Below is the image for my Firebase stucture, where with the help of brown line I have mentioned exact place I want to add the details.
To update/set specific fileds for an object you can follow the dedicated documentation section
Your code should like like this
private void setUserData(String userId, double lat, double lng) {
Map<String, Object> userUpdates = new HashMap<>();
userUpdates.put("/users/" + userId + "/name_you_want/address", "Groove Street 2");
userUpdates.put("/users/" + userId + "/name_you_want/lat", lat);
userUpdates.put("/users/" + userId + "/name_you_want/lng", lng);
mDatabase.updateChildren(userUpdates, /*Add a complete listener if wanted*/);
}
EDIT: to avoid the extra id, you just need to specify the node name, just by replacing "name_you_want"

Remove DataSnapshot From Firebase setValue()

My Firebase database storage format like this.
{
key=3553: 3223,
value={
-KZMFwmCYKevESD6qtjD={
text=Hello I am,
timestamp=[
.sv: timestamp
],
imageUrl=,
senderId=yDapbI755tOD72ivfsdferOv1RIHMnAe03
}
}
}
but at the time of set value to store in firebase database i am doing like this.
String Temp = "{timestamp: [.sv: timestamp], imageUrl: , senderId: " + Utils.SET_HEADER_ID + ", text: " + strMessage + "}";
System.out.println("===== Temp String : " + Temp);
String key = mFirebaseDatabaseReference.child("threads/3333:3333").push().getKey();
mFirebaseDatabaseReference.child("threads/3333:3333").child(key).setValue(Temp);
As I wrote above code I added a data in Firebase database. But it will automatically include DataSnapshot JsonObject at top my insert database format like this, which is wrong.
DataSnapshot{
key=3333: 3333,
value={
-KZPfTKJhaCC4RkIj45P={
timestamp: [
.sv: timestamp
],
imageUrl: ,
senderId: yDapbI755tOD72ivOv1RIHMnAe03,
text: hiiiiiiiii
}
}
}
How can I remove this DataSnapshot from insert format of Firebase?
You cannot pass a raw JSON value to Firebase. You'll instead have to build the data structure in your code:
Map<String,String> map = new HashMap<String,String>();
map.put("timestamp", Firebase.Database.ServerValue.TIMESTAMP);
map.put("imageUrl", "an actual image URL, which is missing from your question");
map.put("senderId", Utils.SET_HEADER_ID);
map.put("text", strMessage);
mFirebaseDatabaseReference.child("threads/3333:3333").child(key).setValue(map);
Alternatively you can use a library such as Jackson to convert the JSON intro the required nested map structure. See for example Nested Json to Map using Jackson.

Firebase , second push() in same method does not work

In my app , there is an activity which upon clicking the save button, 2 sets of data in 2 different places should be made by push(), Since in both places an unique id is needed.
I have followed the sample code in the Firebase guide and added the second push
String userId = auth.getCurrentUser().getUid().toString();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
DatabaseReference firstDatabaseRef = reference.child("first");
DatabaseReference secondDatabaseRef = reference.child("second").child(userId);
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = second.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
childUpdates.put("/second/" + userId + "/" + key + "/" + keySecond, secondValue);
reference.updateChildren(childUpdates);
The result that i got for first was exactly as i expected but for second , instead of creating second/<userId>/<key>/<keySecond>/children, i get this :
"second" : {
//userId
"5TQLPlGf4mbcBRKesQwR30fH1L22" : {
//key
"-KL1030IywlNpkTGC7mU" : {
"secondAmount" : "147",
"Key" : "-KL1030IywlNpkTGC7mU",
"secondName" : "secondName",
"keySecond" : "-KL1030PZlHqD_asSR_8",
}
}
}
Instead of having the final children in another unique id, which by the way is recorded in the keySecond, they are all added directly to the key.
This cannot be accepted since every key must have many keySecond.
I hope that i explained my problem correctly.
Please tell me what am i doing wrong.
How should i modify my code or should i reconsider my data structure completely ?
This is a puzzle. I copy/pasted the code you posted and created stubs for First and Second. Running with Firebase 9.0.2 produced the result shown below, which I believe is what you are expecting. Are you running with a different Firebase version? Is it possible the JSON you posted was produced by a different version of the code you posted?
{
"first" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
"firstAmount" : "FirstAmount",
"firstKey" : "-KL3rXeYrscFQNrVQnHb",
"firstName" : "FirstName"
}
}
},
"second" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
// keySecond
"-KL3rXe_JyY9Vz2U-NES" : {
"Key" : "-KL3rXeYrscFQNrVQnHb",
"keySecond" : "-KL3rXe_JyY9Vz2U-NES",
"secondAmount" : "SecondAmount",
"secondName" : "SecondName"
}
}
}
}
}
When processing the updateChildren(), the Firebase Database loops over the children that you pass and for each key it essentially does a setValue() with the value you passed.
That means that if you have children with overlapping keys, the value of one of those keys will be written last. The order of these is undefined.
In your case it's fairly easy to merge the updates together:
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = trans.toMap();
firstValues.put(keySecond, secondValue); // This is the main change
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
reference.updateChildren(childUpdates);

get array of KEYS for each element under jsonarray

I want to parse my Json array dynamically. and want to get array of KEYS for each element under jsonarray. i an getting this through iterator. but not getting the sequeance as per the output json formate.
my JSON Formate :
{
"result": "Success",
"AlertDetails": [
{
"ShipmentNumber": "SHP34",
"Customer": "BEST",
"DateCreated": "2012-08-29T04:59:18Z"
"CustomerName": "BEST"
},
{
"ShipmentNumber": "SHP22",
"Customer": "BEST",
"DateCreated": "2012-08-29T05:34:18Z"
"CustomerName": "Jelly"
}
]
}
here is My Code :
JSONArray array = jsonobject.getJSONArray("AlertDetails");
JSONObject keyarray = array.getJSONObject(0);
Iterator temp = keyarray.keys();
while (temp.hasNext()) {
String curentkey = (String) temp.next();
KEYS.add(curentkey);
}
Log.d("Parsing Json class", " ---- KEYS---- " + KEYS);
What i am getting in logcate output:
---- KEYS---- [DateCreated,CustomerName, Customer, ShipmentNumber]
What i want :
---- KEYS---- [ShipmentNumber, Customer, DateCreated,CustomerName]
The JSONObject documentation (link: http://developer.android.com/reference/org/json/JSONObject.html) has the following description for the keys() function:
public Iterator keys ()
Since: API Level 1
Returns an iterator of the String names in this object. The returned
iterator supports remove, which will remove the corresponding mapping
from this object. If this object is modified after the iterator is
returned, the iterator's behavior is undefined. The order of the keys
is undefined.
So you may get the keys but the order is undefined. You may use any of the sorting algorithms if you want the keys in any particular order.
EDIT
Since you are unaware of the order of KEYS you are getting from the WS, after receiving the data you may show the details on screen in an ordered format . After building the arraylist KEYS, you may sort it alphabetically using the following:
Collections.sort(KEYS);
This will order the Strings in the KEYS arraylist according to its natural ordering (which is alphabetically).
I just come to know when I press ctlr+space bar, in which its clearly written that behavior of the keys is undefined, orders is not maintain by keys.
Arun George said# correctly that you have to use any sorting method to achieve your goal.
and for sorting may be this link will help you.
Use GSON library from google. It has a a lot of setting to read/create/parse json array and json objects. I didn't test it to find the solution, but I think it's very simple and full featured tool and can solve the problem.
Use different library to parse json dynamically.
Below I wrote a piece of code based on Jackson JSON Processor, which is the best JSON library in my opinion
public void test() throws IOException {
String str = "{\n" +
" \"result\": \"Success\",\n" +
" \"AlertDetails\": [\n" +
" {\n" +
" \"ShipmentNumber\": \"SHP34\",\n" +
" \"Customer\": \"BEST\",\n" +
" \"DateCreated\": \"2012-08-29T04:59:18Z\",\n" +
" \"CustomerName\": \"BEST\"\n" +
" }\n" +
" ]\n" +
"}";
JsonFactory factory = new JsonFactory();
JsonParser jsonParser = factory.createJsonParser(str);
JsonToken jsonToken;
SerializedString alertDetails = new SerializedString("AlertDetails");
while (!jsonParser.nextFieldName(alertDetails)) { /* move to AlertDetails field */ }
jsonParser.nextToken(); // skip [ start array
jsonParser.nextToken(); // skip { start object
// until } end object
while ((jsonToken = jsonParser.nextToken()) != JsonToken.END_OBJECT) {
if (jsonToken == JsonToken.FIELD_NAME) {
System.out.println(jsonParser.getCurrentName());
}
}
}
It simply prints out field names in the same order as in json:
ShipmentNumber
Customer
DateCreated
CustomerName
EDIT
Naturally you can use other libraries like gson etc. But remember, as is written on json.org, that:
An object is an unordered set of name/value pairs.
and the order of keys depends on implementation and might vary in each request.
There is also the method names();
Returns an array containing the string names in this object.
Edit: returns names in undefined order. Suggestions: parse it on your own

Categories

Resources