简体   繁体   English

在没有Seri​​alizeObject的情况下在F#中解析Firebase JSON

[英]Parsing Firebase JSON in F# Without SerializeObject

I am getting the following JSON from firebase: 我从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"}}}

I am currently parsing this in Swift as follows, using the Firebase API: 我目前正在使用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)
        }

    })
}

As you can see, I make my way through the JSON by converting into dictionaries and looping through pairs. 如您所见,我通过转换成字典并成对循环来遍历JSON。

I need to do the same thing now in F# . 我现在需要在F#做同样的事情。 I manage to obtain the JSON using the REST API as there is no native API for Firebase in F#. 我设法使用REST API来获取JSON,因为F#中没有Firebase的本机API。 However, I am completely lost when it comes to parsing this JSON. 但是,在解析此JSON时我完全迷失了。 I managed to come up with the following code: 我设法提出了以下代码:

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 

This allows me to loop through the JSON and read all the values, however I don't think this is suitable here as some of the values might not exist (which is handled by the if let in Swift). 这使我可以遍历JSON并读取所有值,但是由于某些值可能不存在(这由Swift中的if let处理),因此我认为这不合适。 Also, I don't think this maintains the nesting or hierarchy structure of the JSON properly, it simply visits all the values in turn. 另外,我认为这不能正确维护JSON的嵌套或层次结构,它只是依次访问所有值。

I was reading through this tutorial: http://www.hoonzis.com/fsharp-json-serializaton/ however I'm not sure how to use : 我正在阅读本教程: http : //www.hoonzis.com/fsharp-json-serializaton/,但是我不确定如何使用:

JsonConvert.SerializeObject(data)

Am I supposed to simply create an object which mimics the structure of the JSON? 我是否应该简单地创建一个模仿JSON结构的对象? How will dates get handled then, will they be converted automatically? 日期将如何处理,将自动转换? What about doubles stored as Strings etc? 存储为String等的double呢? I would be much more comfortable writing this code myself, like I did in Swift as this would ensure everything is properly parsed, however I do not know where to begin really and how to handle the nesting of the JSON in the code snippet I provided. 我自己编写该代码会更自在,就像我在Swift中所做的那样,因为这可以确保正确解析所有内容,但是我不知道从哪里真正开始以及如何处理我提供的代码片段中的JSON嵌套。

You can either use the JSON Type Provider , as mentioned in the comments, or you can create F# Record Types that match the structure of the JSON document you're working with and use a library like Newtonsoft.Json to deserialize the JSON to your F# records. 您可以使用JSON 类型提供程序 (如注释中所述),也可以创建与您正在使用的JSON文档结构匹配的F# 记录类型 ,并使用Newtonsoft.Json之类的库将JSON反序列化为F#记录。 If you specify the types in your F# record correctly, they will be parsed appropriately by the serializer, and you won't have to traverse the JSON manually. 如果您在F#记录中正确指定了类型,则序列化程序将对其进行适当的解析,而您不必手动遍历JSON。 For nested objects, simply create a record type that matches the structure of the inner document and make it a field in the record for the outer object. 对于嵌套对象,只需创建与内部文档的结构匹配的记录类型,然后使其成为外部对象的记录中的字段。

If you want to know how one would go about parsing JSON in F#, take a look at this tutorial . 如果您想知道如何在F#中解析JSON,请看一下本教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM