Firebase Converting Snapshot Value to Objects

Firebase converting snapshot value to objects

Try using the class, protocol and extension I have created below, it will save you a lot of time trying to map the snapshots to objects.

//
// FIRDataObject.swift
//
// Created by Callam Poynter on 24/06/2016.
//

import Firebase

class FIRDataObject: NSObject {

let snapshot: FIRDataSnapshot
var key: String { return snapshot.key }
var ref: FIRDatabaseReference { return snapshot.ref }

required init(snapshot: FIRDataSnapshot) {

self.snapshot = snapshot

super.init()

for child in in snapshot.children.allObjects as? [FIRDataSnapshot] ?? [] {
if respondsToSelector(Selector(child.key)) {
setValue(child.value, forKey: child.key)
}
}
}
}

protocol FIRDatabaseReferenceable {
var ref: FIRDatabaseReference { get }
}

extension FIRDatabaseReferenceable {
var ref: FIRDatabaseReference {
return FIRDatabase.database().reference()
}
}

Now you can create a model that inherits the FIRDataObject class and can be initialised with a FIRDataSnapshot. Then add the FIRDatabaseReferenceable protocol to your ViewController to get access to your base reference.

import Firebase
import UIKit

class ViewController: UIViewController, FIRDatabaseReferenceable {

var posts: [Post] = []

override func viewDidLoad() {

super.viewDidLoad()

ref.child("posts").observeEventType(.ChildAdded, withBlock: {
self.posts.append(Post(snapshot: $0))
})
}
}

class Post: FIRDataObject {

var author: String = ""
var body: String = ""
var imageURL: String = ""
}

UPDATE for Swift 3

class FIRDataObject: NSObject {

let snapshot: FIRDataSnapshot
var key: String { return snapshot.key }
var ref: FIRDatabaseReference { return snapshot.ref }

required init(snapshot: FIRDataSnapshot) {

self.snapshot = snapshot

super.init()

for child in snapshot.children.allObjects as? [FIRDataSnapshot] ?? [] {
if responds(to: Selector(child.key)) {
setValue(child.value, forKey: child.key)
}
}
}
}

Firebase realtime database DataSnapshot value to Object conversion

In your case the constructor that gets called is the parameterless since you are reading from the database using getValue(), which is required to map the values in the DataSnapshot. According to the doc, these are the rules you must follow to get the DataSnapshot data into a custom Java Class:

  • The class must have a default constructor that takes no arguments

  • The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized.

I you want to set the value for the property fullName you can do it in the same getFullName() method. Something like this:

public String getFullName() { 
if(fullName == null){// it will be null the first time assuming the value doesn't exist in the database.
fullName = getFirstName() + getLastName();
}
return fullName;
}

Swift 4, Firebase how to observe the snapshot and convert into object

Use the below code to get your required values

    guard let uid = Auth.auth().currentUser?.uid else {
return
}

let ref = Database.database().reference().child("users").child("\(uid)")
ref.child("Dream").observe(.value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
print(dictionary["content"] as? String)

}, withCancel: nil)

ref.child("Grocerylist").observe(.value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
print(dictionary["content"] as? String)

}, withCancel: nil)

How to pull snapshot key & values into list through Map ?

In this code you only use the element.value of each node in your results:

return Items.fromRTDB(Map<String, dynamic>.from(element.value));

If you also want to get the key of each item, you will have to also use element.key in there and pass that to your Items object.


Something like this:

Items.fromRTDB(element.key, Map<String, dynamic>.from(element.value));

...

class Items{
final String key;
final String item;
final String expiryDate;
final String quantity;
final String user;

Items({required this.key, required this.item, required this.expiryDate, required this.quantity, required this.user});

//Mapping from real-time database
factory Items.fromRTDB(String key, Map<String, dynamic> data) {
return Items(
key: key,
item: data['item'],
expiryDate: data['exp'],
quantity: data['qty'],
user: data['user'],
);
}
}

Converting DataSnapshot to custom struct object - Swift 4

Managed to solve the problem using a workaround:

This code goes before the viewDidLoad() method of your ViewController

let ref = Database.database().reference().child("alldata")
var companyName: [String] = []
var maxCm: [String] = []
var maxIn: [String] = []
var weightKg: [Int] = []
var weightLb: [Int] = []

And in the viewDidLoad()

override func viewDidLoad() {
super.viewDidLoad()

ref.queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in

let snapshotValue = snapshot.value as! [String:[String:AnyObject]]
let sorted = snapshotValue.sorted() { $0.key.lowercased() < $1.key.lowercased() }

for (key, _) in sorted {

let keys = snapshotValue[key]
let company_name = key
self.companyName.append(company_name)
let carry_max_cm = keys?["keyname"] as! String
self.maxCm.append(carry_max_cm)
let carry_max_in = keys?["keyname"] as! String
self.maxIn.append(carry_max_in)
let carry_weight_kg = keys?["keyname"] as! Int
self.weightKg.append(carry_weight_kg)
let carry_weight_lb = keys?["keyname"] as! Int
self.weightLb.append(carry_weight_lb)

}

self.tableView.reloadData()

}
}

let sorted = snapshotValue.sorted() { $0.key.lowercased() < $1.key.lowercased() }

Orders the dictionary alphabetically

Casting an Object as a Map when Firebase RTDB is updated

Due to changes in version 9 from dynamic to object, you can define the snapshot value as dynamic:

      final event = await resp.once();
_usuario = UsuarioModel.fromJson(Map<String, dynamic>.from(event.snapshot.value as dynamic));

It's a workaround, but it does work!



Related Topics



Leave a reply



Submit