【问题标题】:Parsing Firebase JSON in F# Without SerializeObject在没有 SerializeObject 的 F# 中解析 Firebase JSON
【发布时间】:2018-06-28 22:44:36
【问题描述】:

我从 firebase 获得以下 JSON:

{"listings":{"-cecececee-oha-":{"listing_id":"-xsxsxsxsxs-oha-","location":"Edinburgh"},"-xsxssxxsxs":{"listing_id":"-xsxsxsxs","location":"Edinburgh","messages":{"xsxsxsxs":{"-xsxssxxs":{"senderId":"wdwdwwd","senderName":"wddwdw","text":"Hey there"},"-L19r0osoet4f9SjBGE7":{"senderId":"cddccdcd","senderName":"dccd","text":"Hi"}}}},"-cdcdcdcd":{"listing_id":"-cdcdcdcd","location":"Edinburgh","messages":{"879dUqGuiXSd95QHzfhbSs05IZn2":{"-L1i6c7sGf3BcF2cCSCu":{"senderId":"879dUqGuiXSd95QHzfhbSs05IZn2","senderName":"cddcdcdcd","text":"cdcddccdcd"}},"cddcdccdcd":{"-L19FGCMuQACjYKCFEwV":{"senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1","senderName":"dccdcdcd","text":"Hey"},"-cdcdcdcdcd-":{"senderId":"cdcdcdcd","senderName":"dcdccdcd","text":"cdcddccd"},"-cdcdcdcd":{"senderId":"cdcdcdcdcd","senderName":"cdcdcdcdcd","text":"How are you"}}}},"-cdcdcdcd-dccd":{"listing_id":"-cdcdcdcd-JCbiAnN","location":"Edinburgh"},"-dccdcdcdcd-EKCq2":{"listing_id":"-cdcdcdcd-EKCq2","location":"Edinburgh"},"-cddccdcdcd":{"listing_id":"-cdcdcddcdc","location":"Edinburgh"}}}

我目前正在使用 Firebase API 在 Swift 中进行如下解析:

 _ = Database.database().reference().child("users").child(UserDefaults.standard.object(forKey: "uid") as! String).observeSingleEvent(of : .value, with: { (snapshot) in
        var matches_list = [ChatMatch]()
        if let matches = snapshot.childSnapshot(forPath: "listings").value as? [String:AnyObject] {
            for (str,_) in matches {
                if let dictionary = snapshot.childSnapshot(forPath: "listings").childSnapshot(forPath: str).value as? [String:AnyObject] {
                    let location = dictionary["location"] as! String
                    let a = ChatMatch()
                    a.id = str
                    a.location = location
                    if let pairs = snapshot.childSnapshot(forPath: "listings").childSnapshot(forPath: str).childSnapshot(forPath:"messages").value as? [String:AnyObject] {
                        for (str1,_) in pairs {
                            if let dic = snapshot.childSnapshot(forPath: "listings").childSnapshot(forPath: str).childSnapshot(forPath:"messages").childSnapshot(forPath: str1).value as? [String:AnyObject] {
                                for (str2, _)  in dic {
                                    if let dic2 = snapshot.childSnapshot(forPath: "listings").childSnapshot(forPath: str).childSnapshot(forPath:"messages").childSnapshot(forPath: str1).childSnapshot(forPath: str2).value as? [String:AnyObject] {
                                        if let senderid = dic2["senderId"] as? String {
                                            if (senderid != UserDefaults.standard.object(forKey: "uid") as! String) {
                                                a.matchid = senderid
                                            }
                                        }
                                        if let senderName = dic2["senderName"] as? String {
                                            if (senderName != UserDefaults.standard.object(forKey: "name") as! String) {
                                                a.matchName = senderName
                                                matches_list.append(a)
                                                break
                                            }
                                        }
                                    }
                                }



                            }
                        }
                }
            }
        }
        }

        for match in matches_list {

            Database.database().reference().child("listings").child(match.location!).child(match.id!).observeSingleEvent(of: .value, with: { (snapshot2) in
                if let dict = snapshot2.value as? [String : Any] {
                    let new_listing = Listing()

                    let fromString = dict["from"] as! String
                    let toString = dict["to"] as! String
                    let landlordId = dict["landlord_id"] as! String
                    let landlordName = dict["name"] as! String
                    let listingId = dict["listing_id"] as! String
                    let pic1url = dict["pic_1_url"] as! String
                    let pic2url = dict["pic_2_url"] as! String
                    let pic3url = dict["pic_3_url"] as! String
                    let pic4url = dict["pic_4_url"] as! String
                    let pic5url = dict["pic_5_url"] as! String
                    let pricepernight = dict["price_per_night"] as! String
                    let postcode = dict["postcode"] as! String
                    let location = dict["location"] as! String

                    let dateFormatter = DateFormatter()
                    dateFormatter.dateFormat = "dd/mm/yyyy"
                    dateFormatter.timeZone = TimeZone(abbreviation: "GMT+0:00")

                    let fromdate = dateFormatter.date(from: fromString)
                    new_listing.from = fromdate

                    let todate = dateFormatter.date(from: toString)
                    new_listing.to = todate

                    new_listing.landlordId = landlordId
                    new_listing.landlordName = landlordName
                    new_listing.listingId = listingId
                    new_listing.pricePerNight = Int(String(pricepernight.suffix(pricepernight.count - 1)))!
                    if (pic1url != "none") {
                        new_listing.pic1url = URL(string: pic1url)
                    }
                    if (pic2url != "none") {
                        new_listing.pic2url = URL(string: pic2url)
                    }
                    if (pic3url != "none") {
                        new_listing.pic3url = URL(string: pic3url)
                    }
                    if (pic4url != "none") {
                        new_listing.pic4url = URL(string: pic4url)
                    }
                    if (pic5url != "none") {
                        new_listing.pic5url = URL(string: pic5url)
                    }
                    new_listing.postcode = postcode
                    new_listing.location = location
                    new_listing.partnername = match.matchName
                    new_listing.partnerid = match.matchid
                    listings.append(new_listing)
                    if (matches_list.index(of: match) == matches_list.count - 1) {
                        completionHandler(true, listings)
                        return
                    }
                }
            })
        }
        if (matches_list.count == 0) {
            completionHandler(false, listings)
        }

    })
}

如您所见,我通过转换成字典并循环遍历 JSON 来完成我的工作。

我现在需要在F# 中做同样的事情。我设法使用REST API 获取 JSON,因为 F# 中没有适用于 Firebase 的本机 API。但是,在解析这个 JSON 时,我完全迷失了。我设法想出了以下代码:

let myCallbackGetChats (reader:IO.StreamReader) url = 
    let html = reader.ReadToEnd()
    let reader : JsonTextReader = new JsonTextReader(new StringReader(html))

    while (reader.Read()) do 
        if reader.Value <> null then 
            let value = reader.Value :?> String 

这允许我遍历 JSON 并读取所有值,但是我认为这不适合这里,因为某些值可能不存在(由 Swift 中的 if let 处理)。另外,我认为这不能正确维护 JSON 的嵌套或层次结构,它只是依次访问所有值。

我正在阅读本教程:http://www.hoonzis.com/fsharp-json-serializaton/ 但是我不知道如何使用:

JsonConvert.SerializeObject(data)

我是否应该简单地创建一个模仿 JSON 结构的对象?那么日期将如何处理,它们会自动转换吗?存储为字符串等的双打怎么样?我自己编写这段代码会更舒服,就像我在 Swift 中所做的那样,因为这将确保所有内容都被正确解析,但是我不知道真正从哪里开始以及如何处理代码 sn-p 中 JSON 的嵌套假如。

【问题讨论】:

标签: ios json swift firebase-realtime-database f#


【解决方案1】:

您可以使用 JSON Type Provider,如 cmets 中所述,或者您可以创建与您正在使用的 JSON 文档的结构相匹配的 F# Record Types,并使用像 Newtonsoft.Json 这样的库来反序列化JSON 到您的 F# 记录。如果您正确指定 F# 记录中的类型,它们将由序列化程序适当地解析,您不必手动遍历 JSON。对于嵌套对象,只需创建与内部文档结构匹配的记录类型,并将其作为外部对象的记录中的字段。

如果您想知道如何在 F# 中解析 JSON,请查看 this tutorial

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 2016-09-30
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2013-03-27
    相关资源
    最近更新 更多