可以将Swift 4的JSONDecoder与Firebase实时数据库一起使用吗?

waz*_*woo 11 json json-deserialization swift firebase-realtime-database

我正在尝试解码Firebase DataSnapshot中的数据,以便可以使用JSONDecoder对其进行解码.

当我使用URL通过网络请求访问它(获取Data对象)时,我可以正确解码此数据.

不过,我想用火力地堡API直接获取数据,使用observeSingleEvent上描述这个页面.

但是,当我这样做时,我似乎无法将结果转换为Data对象,我需要使用JSONDecoder.

是否可以使用DataSnapshot进行新的JSON解码?这怎么可能?我似乎无法弄明白.

Noo*_*ass 21

我创建了一个名为库CodableFirebase,提供EncodersDecoders被用于火力地堡设计的.

所以对于上面的例子:

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)
Run Code Online (Sandbox Code Playgroud)

以下是您将如何阅读相同的数据:

Database.database().reference().child("pathToGraceryItem").observeSingleEvent(of: .value, with: { (snapshot) in
    guard let value = snapshot.value else { return }
    do {
        let item = try FirebaseDecoder().decode(GroceryItem.self, from: value)
        print(item)
    } catch let error {
        print(error)
    }
})
Run Code Online (Sandbox Code Playgroud)


Err*_*rol 8

我通过将快照转换回数据格式的JSON,使用JSONDecoder转换了Firebase快照.您的结构需要符合Decodable或Codable.我用SwiftyJSON完成了这个,但是这个例子使用的是JSONSerialization,它仍然有效.

JSONSnapshotPotatoes {
    "name": "Potatoes",
    "price": 5,
}
JSONSnapshotChicken {
    "name": "Chicken",
    "price": 10,
    "onSale": true
}

struct GroceryItem: Decodable {
    var name: String
    var price: Double
    var onSale: Bool? //Use optionals for keys that may or may not exist
}


Database.database().reference().child("grocery_item").observeSingleEvent(of: .value, with: { (snapshot) in
        guard let value = snapshot.value as? [String: Any] else { return }
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: value, options: [])
            let groceryItem = try JSONDecoder().decode(GroceryItem.self, from: jsonData)

            print(groceryItem)
        } catch let error {
            print(error)
        }
    })
Run Code Online (Sandbox Code Playgroud)

请注意,如果您的JSON密钥与您的Decodable结构不同.你需要使用CodingKeys.例:

JSONSnapshotSpinach {
    "title": "Spinach",
    "price": 10,
    "onSale": true
}

struct GroceryItem: Decodable {
    var name: String
    var price: Double
    var onSale: Bool?

    enum CodingKeys: String, CodingKey {
        case name = "title"

        case price
        case onSale
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处使用Apple Docs找到有关此内容的更多信息.


Ric*_*iel 6

不可以。Firebase 返回无法解码的 FIRDataSnapshot。但是,您可以使用这种结构,它非常简单且易于理解:

struct GroceryItem {
  
  let key: String
  let name: String
  let addedByUser: String
  let ref: FIRDatabaseReference?
  var completed: Bool
  
  init(name: String, addedByUser: String, completed: Bool, key: String = "") {
    self.key = key
    self.name = name
    self.addedByUser = addedByUser
    self.completed = completed
    self.ref = nil
  }
  
  init(snapshot: FIRDataSnapshot) {
    key = snapshot.key
    let snapshotValue = snapshot.value as! [String: AnyObject]
    name = snapshotValue["name"] as! String
    addedByUser = snapshotValue["addedByUser"] as! String
    completed = snapshotValue["completed"] as! Bool
    ref = snapshot.ref
  }
  
  func toAnyObject() -> Any {
    return [
      "name": name,
      "addedByUser": addedByUser,
      "completed": completed
    ]
  }
  
}
Run Code Online (Sandbox Code Playgroud)

并使用 toAnyObject() 保存您的项目:

let groceryItemRef = ref.child("items")

groceryItemRef.setValue(groceryItem.toAnyObject())
Run Code Online (Sandbox Code Playgroud)

来源:https : //www.raywenderlich.com/139322/firebase-tutorial-getting-started-2