天道酬勤,学无止境

将 Firebase 数据快照转换为可编码的 JSON 数据(Converting Firebase Datasnapshot to codable JSON data)

问题

我正在使用 Firebase 数据库,并且正在尝试使用NSObject检索和使用数据。 我在运行应用程序时收到NSUnknownKeyException错误,导致它崩溃。

NS对象:

class WatchList: NSObject {

    var filmid: Int?

}

Firebase 代码:

ref.child("users").child(uid!).child("watchlist").observe(DataEventType.childAdded, with: { (info) in
    print(info)
    
    if let dict = info.value as? [String: AnyObject] {
        let list = WatchList()
        list.setValuesForKeys(dict)
        print(list)
    }        
}, withCancel: nil)

我不确定是什么原因造成的。

此外,为了增强这个解决方案是他们获取这些数据的一种方式,而不是使用 NSObject,而是使用CodableJSONDecoder与 Firebase 数据?

回答1

现在是 2021 年。

Firebase 终于增加了对 Firestore 文档解码的支持。 只需让您的对象符合Codable并像这样解码:

let result = Result {
  try document?.data(as: City.self)
}
switch result {
case .success(let city):
    if let city = city {
        print("City: \(city)")
    } else {
        print("Document does not exist")
    }
case .failure(let error):
    // A `City` value could not be initialized from the DocumentSnapshot.
    print("Error decoding city: \(error)")
}

只是不要忘记添加'FirebaseFirestoreSwift' pod,然后将其导入您的文件中。

阅读更多:https://firebase.google.com/docs/firestore/query-data/get-data#custom_objects

原始答案

在这里使用的一个非常好的库是 Codable Firebase,我也在我的项目中使用它。 只需使您的类/结构符合Codable协议并使用 FirebaseDecoder 将您的 Firebase 数据解码为 Swift 对象。

例子:

Database.database().reference().child("model").observeSingleEvent(of: .value, with: { snapshot in
    guard let value = snapshot.value else { return }
    do {
        let model = try FirebaseDecoder().decode(Model.self, from: value)
        print(model)
    } catch let error {
        print(error)
    }
})
回答2

您可以简单地使用 JSONSerialization 将快照值属性从Any转换为Data

let data = try? JSONSerialization.data(withJSONObject: snapshot.value)

您还可以扩展 Firebase DataSnapshot 类型并向其添加数据和 json 字符串属性:

import Firebase 

extension DataSnapshot {
    var data: Data? {
        guard let value = value, !(value is NSNull) else { return nil }
        return try? JSONSerialization.data(withJSONObject: value)
    }
    var json: String? { data?.string }
}
extension Data {
    var string: String? { String(data: self, encoding: .utf8) }
}

用法:

guard let data = snapshot.data else { return }

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Firebase将快照值转换为对象(Firebase converting snapshot value to objects)
    问题 所以我有一个postDict作为[String: AnyObject]并且我有一个模型类Post 。 有没有一种快速的方法可以将postDict转换为Post对象数组,以便在使单元出队时将是: cell.textLabel.text = posts[indexPath.item].author import UIKit import Firebase class ViewController: UIViewController { var posts = [Post]() override func viewDidLoad() { super.viewDidLoad() let ref = FIRDatabase.database().reference().child("posts").queryLimitedToFirst(5) ref.observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot) in let postDict = snapshot.value as! [String : AnyObject] print(postDict) //convert postDict to array of Post objects }) } } class Post: NSObject { var
  • Android Firebase - 无法从 Firebase 快照接收正确的 JSON(Android Firebase - Can't receive proper JSON from Firebase snapshot)
    问题 我的 android 应用程序连接到 Firebase 并提取由我的服务器发送到那里的“警报对象”。 当我从 Firebase 导出数据时,我得到了格式精美的数据 JSON 表示。 问题:当我使用 DataSnapshot 将数据拉到我的 android 设备时,数据有“=”(等号)而不是“:”(分号)。 也没有报价单。 当我尝试做类似JSONObject alert = new JSONObject(data.getValue().toString()); 由于明显的原因,我收到错误。 我说这是显而易见的,因为如果您查看我的代码打印到控制台的内容,您会发现它不再是有效的 JSON 格式。 一个朋友提到我需要对编码做一些事情,但我们没有时间讨论。 我如何遍历我创建的这些(有点奇怪)警报对象并将它们转换为我的 Java 中的 JSON 对象,以便我可以访问它们的属性,如alert.date和alert.message 。 我认为屏幕截图会帮助您了解我在做什么。 Firebase 根本没有安全保护,因此您可以随意查看它。 它不会真正起多大作用,当我进入生产阶段时,无论如何我都会移动它。 我相信这是一个非常容易回答的问题,我只是不太熟悉 JSON 和整个编码。 谢谢! 回答1 你可以使用 gson 库 public void onChildAdded(DataSnapshot
  • 将 Firebase 数据库转换为 Cloud Firestore [关闭](Converting Firebase Database to Cloud Firestore [closed])
    问题 关闭。 这个问题需要更加集中。 它目前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑这篇文章来关注一个问题。 2年前关闭。 改进这个问题 祝大家都能收到有关 Firebase Cloud Firestore 的好消息。 由于我想将我的Firebase 数据库转换为Cloud Firestore ,有什么简单的方法可以转换它吗? 我想继续使用 Cloud Firestore。 回答1 我在学习新事物时为自己编写指南。 这是我的指南,描述了我如何将实时数据库迁移到 Cloud Firestore。 您可以跳过第一部分。 我是用 Markdown 写的,有些代码标记没有转换成 StackOverflow 的标记。 如果您在阅读时遇到问题,我会将原始 Markdown 版本通过电子邮件发送给您。 现在我正在将控制器更新为 Cloud Firestore 查询。 从 Firebase 实时数据库迁移到 Cloud Firestore 为什么,为什么不,Firebase 实时数据库? 两年多来,我的首选堆栈是 Angular 和 Firebase。 数据绑定引起了我的注意——如果用户更改视图中的数据,控制器和云数据库中的数据会立即更改。 或任何其他事件顺序。 我的第一个 Firebase 项目是一个井字游戏,两个玩家可以远程玩,我的点击会立即出现在你的屏幕上,反之亦然
  • firebase json反序列化迅速(firebase json deserialization swift)
    问题 我有我需要在字典中输入的 JSON 数据,然后附加到一个数组中。 下面是应该发生的地方,但我收到错误 此类不符合密钥 K0tA3yTnxAWxCFBZoeyAjcr3yYy1 的密钥值编码。 let room = rooms[indexPath.row] if let dictionary = room.members { let user = User() user.setValuesForKeys(dictionary) liveCell.members.append(user) } 下面是课程 用户 class User: NSObject { var email: String? var name: String? var profileImageUrl: String? } 房间 class Room: NSObject { var rid: String? var owner: String? var groupChatName: String? var groupChatDescription: String? var members: NSDictionary? } 数据库中的房间对象 "rooms" : { "B7C7E469-945E-4327-9473-AAE34FCB9B41" : { "groupChatDescription" : "123ae"
  • Swift 3 中的 Firebase 访问快照值错误(Firebase Accessing Snapshot Value Error in Swift 3)
    问题 我最近升级到 swift 3 并且在尝试从快照观察事件值访问某些内容时遇到错误。 我的代码: ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in let username = snapshot.value!["fullName"] as! String let homeAddress = snapshot.value!["homeAddress"] as! [Double] let email = snapshot.value!["email"] as! String } 错误围绕上述三个变量并指出: 类型“任何”没有下标成员 任何帮助将非常感激 回答1 我认为您可能需要将您的snapshot.value为NSDictionary 。 ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in let value = snapshot.value as? NSDictionary let username = value?["fullName"] as? String ?? "" let homeAddress = value?[
  • Firebase queryOrderedByChild() 方法未提供排序数据(Firebase queryOrderedByChild() method not giving sorted data)
    问题 我的数据库结构是这样的: { "users": { "alovelace": { "name": "Ada Lovelace", "score": 4, }, "ghopper": { ... }, "eclarke": { ... } } } 我正在尝试按降序检索前 20 名。 let queryRef = FIRDatabase.database().reference().child("users").queryOrderedByChild("score").queryLimitedToLast(20) queryRef.observeSingleEventOfType(.Value, withBlock: { (querySnapShot) in print(querySnapShot.value) }) 我正在尝试获得类似的输出 score": 4 score": 3 score": 2 or score": 2 score": 3 score": 4 or 2 3 4 请让我知道如何解决这个问题。 回答1 使用方法observeEventType而不是observeSingleEventOfType 。 此外,将 FIRDataEventType 设为ChildAdded 。 最后,如果您想要前 20 个项目
  • 如何快速解析 Firebase FDatasnapshot json 数据(how parsing Firebase FDatasnapshot json data in swift)
    问题 我在从 Firebase 获取数据时遇到问题。 时间表是 { title: "dog", images: { main: "dog.png", others: { 0: "1.png", 1: "2.png", 2: "3.png" } } } 如何将 FDataSnapshot 解析为 swift 模型? 回答1 Firebase 是一个 NoSQL JSON 数据库,没有架构和表。 数据以带有节点的“树”结构存储; 父母和孩子。 您无需解析 Firebase JSON 数据即可访问它,您可以直接访问它。 FDataSnapshots 包含一个 .key,它是 Firebase 和 .value 中的父键。 .Value 可以包含一个节点,也可以包含多个节点。 值将具有表示快照中数据的键:值对 因此,对于您的示例,您将拥有这样的 Firebase 结构 dogs dog_id_0 title: "dog" type: "Alaskan Malamute" images: main: "dog.png" others: 0: "1.png" 1: "2.png" dog_id_1 title: "another dog" type: "Boxer" images: main: "another_dog.png" others: 0: "3.png" 1: "4.png" 因此
  • Swift 4 的 JSONDecoder 可以与 Firebase 实时数据库一起使用吗?(Can Swift 4's JSONDecoder be used with Firebase Realtime Database?)
    问题 我正在尝试从 Firebase DataSnapshot 解码数据,以便可以使用 JSONDecoder 对其进行解码。 当我使用 URL 通过网络请求(获取 Data 对象)访问它时,我可以很好地解码这些数据。 但是,我想使用 Firebase API 直接获取数据,使用observeSingleEvent 如本页所述。 但是,当我这样做时,我似乎无法将结果转换为 Data 对象,我需要使用 JSONDecoder。 是否可以使用 DataSnapshot 进行新风格的 JSON 解码? 这怎么可能? 我似乎无法弄清楚。 回答1 我创建了一个名为 CodableFirebase 的库,它提供专为 Firebase 设计的Encoders和Decoders 。 所以对于上面的例子: import Firebase import CodableFirebase let item: GroceryItem = // here you will create an instance of GroceryItem let data = try! FirebaseEncoder().encode(item) Database.database().reference().child("pathToGraceryItem").setValue(data) 以下是读取相同数据的方式:
  • 如何遍历 Firebase 数据快照子子项? 扑(How to loop through a Firebase datasnapshot sub childrens? Flutter)
    问题 我有一个 DataSnapshot JSON 对象: {fridge2: true, fridge1: true} //data pulled from a real time firebase database 我必须将fridge2和fridge1放在这样的列表中: List<String> fridges; 我的尝试: DataSnapshot fridgesDs = snapshot.value['fridges']; for (var fridge in fridgesDs) { if (fridge.value) { fridges.add(fridge.key); } } 给我这个错误: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Iterable<dynamic>' 回答1 我解决了。 我以前print(fridgesDs.runtimeType); 获取 firebase 返回的变量类型。 它实际上是一个 HashMap: _InternalLinkedHashMap<dynamic, dynamic>将返回值转换为Map 。 最后,我使用 forEach 循环遍历地图。 这是最终版本: Map<dynamic, dynamic> fridgesDs =
  • Firebase按顺序获取数据(Firebase getting data in order)
    问题 我正在使用Firebase,直到最近我都没有按字母顺序获取数据的问题。 我从来没有使用过查询,我总是只使用数据快照并逐一对其进行排序。 最近,在snapVal中,数据并不总是按字母顺序排列。 如何做到这一点,以便获得按字母顺序排序的数据的snapVal,就像数据库快照中的数据一样? 真实示例:有4条消息,id1-id4(按此顺序)。 它们包含消息“ 1”-“ 4”。 快照看起来正确。 但是snapVal(snapshot.value)看起来像这样: ["id2": { DATE = "10/20/16"; "FIRST_NAME" = first; ID = userID; "LAST_NAME" = last; MESSAGE = 2; TIME = "8:12 PM"; }, "id4": { DATE = "10/20/16"; "FIRST_NAME" = first; ID = userID; "LAST_NAME" = last; MESSAGE = 4; TIME = "8:12 PM"; }, "id1": { DATE = "10/20/16"; "FIRST_NAME" = first; ID = userID; "LAST_NAME" = last; MESSAGE = 1; TIME = "8:12 PM"; }, "id3": { DATE =
  • 从 Firebase 读取/检索数据(Reading/Retrieving Data From Firebase)
    问题 我是 Swift 3 的初学者(使用 iOS 8.3)。 我一直试图找出一种方法来分离数据,但没有走运。 基本上,我能够从 Firebase 中提取以下数据: { Database = { Kelvin = { Institution = xxx; "Years of Experience" = "2.5"; location = London; }; Sophia = { Institution = xxxx; "Years of Experience" = 3; location = London; }; }; Users = { SOOlIFsjn3839jcmlBbVEnSRH3 = { email = "testing@gmail.com"; password = 1234567; }; }; } 但是现在我想分离数据,以便它显示如下内容: var ref: FIRDatabaseReference! ref = FIRDatabase.database().reference() ref.observe(FIRDataEventType.value, with: { (snapshot) in if let mydata = snapshot.value as? NSDictionary { print(mydata) if let namedata =
  • 转换为新的 Firebase - 枚举(Converting to new firebase - enums)
    问题 今天我尝试迁移到新的 (Google) Firebase。 不仅API不同,数据在数据库中的存储方式也不同。 例如,在数据库中保存为“7.5”的数字 (Double) 在最初由旧 Firebase 以这种方式写入数据库时​​未正确解析(标识为字符串)。 必须手动重写双打(“7.5”到 7.5)、布尔值(“真”到真)等的数据库。 现在我遇到了一个新问题。 尝试将枚举写入数据库时​​出现错误: 致命异常:主进程:com.aayaffe.sailingracecoursemanager,PID:21845 java.lang.RuntimeException:无法启动活动 ComponentInfo{com.aayaffe.sailingracecoursemanager/com.aayaffe.sailingracecoursemanager.map.GoogleMapsActivity}:com.google.firebase. database.DatabaseException:在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2658) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java
  • 使用负时间戳按降序对Firebase数据进行排序(Sort firebase data in descending order using negative timestamp)
    问题 上面是我的Firebase数据库的屏幕截图。 我正在尝试使用负时间戳按降序对Firebase数据进行排序。 我正在使用以下命令: const feedRef = database.ref('ducks') feedRef.orderByChild('timestamp').on('value', (snapshot, error) => { const feed = snapshot.val()}) 我一直以与数据库相同的顺序获取提要,而不是像我想要的那样以降序排列。我认为它无法正常工作,因为ducks端点没有子名称时间戳,我将如何实现呢? 推送生成的键是否包含时间戳数据? 回答1 当您在快照上调用.val()时,它将转换为JSON对象。 而且,根据定义,JavaScript对象中的键是无序的(尽管许多实现将按字典顺序对键进行迭代)。 如果您在Firebase数据库上运行查询,则必须确保在以正确的顺序获取项目之前,不要将其转换为JSON。 在您的情况下,通过使用DataSnapshot.forEach(): const feedRef = database.ref('ducks') var feed = []; feedRef.orderByChild('timestamp').on('value', (snapshot, error) => { snapshot
  • orderByChild无法在Firebase中使用(orderByChild not working in Firebase)
    问题 我试图查询我的数据库,以便它基于子键检索有序列表。 我按如下操作(见下文),但是什么也没有发生,这意味着它返回的对象的排序方式与存储在Firebase数据库中的方式完全相同。 到底是怎么回事? self.getAllProfiles = function () { var qProfile = $q.defer(); var ref = new Firebase(FBURL); ref.child("users").orderByChild('last_update').on("value", function (snapshot) { console.log(snapshot.val()) // HERE IS WHERE IT SHOULD BE ORDERED qProfile.resolve(snapshot.val()); }, function (errorObject) { qProfile.reject(errorObject); }); return qProfile.promise; }; 要添加,我的用户节点如下所示: users /$username /last_update /id /data /profile_image /display_name 这是快照: Tester: Object github: Object last_update
  • Firebase 2.0 - 从 FIRDataSnapshot 读取数据不起作用(Firebase 2.0 - Reading data from FIRDataSnapshot not working)
    问题 我有一个搜索栏,当您键入时,它会在数据库中搜索该用户的用户名。 查找用户名的代码有效,但是当我尝试读取特定值时它崩溃了。 这是代码 func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { Database.child("users").queryOrderedByChild("username").queryEqualToValue(searchText).observeSingleEventOfType(.Value, withBlock: { snapshot in print(snapshot) print(snapshot.value!["first_name"] as? String) print(snapshot.value!["last_name"] as? String) print(snapshot.value!["username"] as? String) print(snapshot.value!["profile_picture_url"] as? String) }) } 打印快照的结果是 Snap (users) { 12345UIDEXample = { "first_name" = Bob; "last_name" = Someone;
  • Firebase 中现有类型的快照之间有什么区别?(What is the difference between existing types of snapshots in Firebase?)
    问题 随着我的代码和我在 Flutter 中的编码经验的进一步发展。 在使用 Firebase API 时,我遇到了不同类型的快照。 我说的是 AsyncSnapshots、QuerySnapshots、DocumentSnapshots 和 DataSnapshots。 如果有更多请给他们起名字。 我想知道这些快照之间的确切区别是什么。 到目前为止,我认为 AsyncSnapshot 可能是异步拍摄的快照,这意味着小部件是在快照数据可用之前构建的,因此使其异步(如果我错了,请纠正我)。 这是我的困惑开始的地方,快照到底是什么? 以及它们每个中的“数据”是什么。 例如:为什么同一个函数不能检索所有快照中所需的数据,而只能在特定快照上运行。 为什么需要将数据从 QuerySnapshot 转换为 DocumentSnapshot,以使其可访问(如果我错了,请再次纠正我)? DocumentSnapshot 和 DataSnapshot 之间的确切区别是什么。 当它们都返回 Maps 时,为什么它们的调用方式不同? 先感谢您。 回答1 据我所知,您是在 Flutter 的上下文中提出这个问题的,所以我将在下面回答这个问题。 Firebase 中有两个数据库:原始的实时数据库和较新的 Cloud Firestore。 今天两者都是同样有效的选项,但它们与自己的 API 完全分开。
  • 尝试在Swift中将Firebase时间戳转换为NSDate(Trying to convert Firebase timestamp to NSDate in Swift)
    问题 我正在尝试在Swift应用程序中使用Firebase时间戳。 我想将它们存储在Firebase中,并将其用作应用程序中的本机NSDate对象。 文档说他们是Unix时代,所以我试过了: NSDate(timeIntervalSince1970:FirebaseServerValue.timestamp) 没有运气。 这: FirebaseServerValue.timestamp 退货 0x00000001199298a0 根据调试器。 传递这些时间戳的最佳方法是什么? 回答1 ServerValue.timestamp()工作方式与在Firebase中设置普通数据略有不同。 它实际上没有提供时间戳。 而是提供一个值,该值告诉Firebase服务器用时间填写该节点。 通过使用此选项,您应用的时间戳全部来自一个来源,即Firebase,而不是用户设备碰巧所说的任何时间戳。 当您(从观察者)取回该值时,您将获得自该纪元以来的时间(以毫秒为单位)。 您需要将其转换为秒以创建NSDate。 这是一段代码: let ref = Firebase(url: "<FIREBASE HERE>") // Tell the server to set the current timestamp at this location. ref.setValue(ServerValue
  • Swift 从 Firebase 数据库中获取特定值(Swift Get Specific Value From Firebase Database)
    问题 我正在尝试从 Firebase 数据库中获取特定值。 我查看了一些文档,例如 Google 的文档,但我做不到。 这是数据库的JSON文件: { "Kullanıcı" : { "ahmetozrahat25" : { "E-Mail" : "ahmetozrahat25@gmail.com", "Yetki" : "user" }, "banuozrht" : { "E-Mail" : "banuozrahat@gmail.com", "Yetki" : "user" } } } SWIFT代码: ref?.child("Kullanıcı").child(userName.text!).observeSingleEvent(of: .value, with: { (snapshot) in if let item = snapshot.value as? String{ self.changedName = item } }) 我想获得一个用户E-Mail价值,而不是每个人的。 我怎样才能做到这一点? 回答1 最后我找到了解决方案。 如果我声明一个 var 并尝试稍后使用它返回 nil,但如果我尝试使用snapshot.value as? String snapshot.value as? String问题。 这是我做的一个例子。 ref
  • 如何检查Firebase数据库值是否存在?(How do I check if a firebase database value exists?)
    问题 我正在将实时数据库与Google的Firebase配合使用,并且正在尝试检查是否存在孩子。 我的数据库结构如下 - / (root) - /users/ –- /james/ -- /jake/ - /rooms/ -- /room1/ --- (room 1 properties) -- /room2/ --- (room 2 properties) 我想检查一下room1是否存在。 我尝试了以下方法: let roomName:String = "room1" roomsDB.child(roomName).observeSingleEventOfType(.Value) { (snap:FIRDataSnapshot) in let roomExists:Bool = snap.value != nil ? "TAKEN" : "NOT TAKEN" } 在访问snap.value它返回该房间的属性的JSON,但是我如何检查房间( /rooms/room1/ )是否开头? 评论是否需要任何澄清 回答1 self.ref = FIRDatabase.database().reference() ref.child("rooms").observeSingleEvent(of: .value, with: { (snapshot) in if snapshot
  • 使用 Codable 和 CodableFirebase 快速解析 Firebase 值时为零(Getting nil in parsing Firebase values swift using Codable and CodableFirebase)
    问题 我正在使用 Firebase 实时数据库,在 swift 和外部库 CodableFirebase 中使用可编码方法。 我已经创建了模型结构,但是当我尝试使用模型结构解析值(因为我正在获取所有值)时,它给了我零。 我的数据库有键,我可能没有正确处理嵌套值。 请帮忙。 谢谢 附上数据库结构快照。 代码: Database.database().reference().child("users").observeSingleEvent(of: .value, with: { (snapshot) in guard let value = snapshot.value as? [String: Any] else { return } do { let friendList = try FirebaseDecoder().decode(Response.self, from: value) guard let conversationUid = value["conversationUid"] as? String, let friendStatus = value["friendStatus"] as? String, let notify = value["notify"] as? Bool, let phNumber = value["phoneNumber"] as