在将响应转换为字典时,已针对已解析响应更改了顺序

时间:2018-04-21 05:30:08

标签: ios json swift4

我从远程服务器获得响应,我从中创建了一个jsonObject。现在,当我重复关键"实例"的响应时其中包含一个字典值,响应被洗牌。作为日期的字典的关键元素在打印时不是按顺序出现的。

这是json的回复:

{
    "data": [
        {
            "id": "apkqY19RthbN",
            "theater_id": "clzEVgztkcWB",
            "theater_audi_id": "7LFeNCaCrm8h",
            "movie_lang_id": "0VTEIjLeDxK1",
            "booking_start_date": null,
            "instances": {
                "2018-04-20": [
                    {
                        "id": "WRK81ahlWcZZ",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "cDqZjYKHP2xt",
                        "show_time": "20:00:00"
                    }
                ],
                "2018-04-21": [
                    {
                        "id": "DcVQhohv9C3W",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "bZOUk3AT6TMM",
                        "show_time": "20:00:00"
                    }
                ],
                "2018-04-22": [
                    {
                        "id": "5YJAydTua6b2",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "qKGXgWvV0r38",
                        "show_time": "20:00:00"
                    }
                ],
                "2018-04-23": [
                    {
                        "id": "AGciEXINppMe",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "YbKFBJV67hFW",
                        "show_time": "20:00:00"
                    }
                ],
                "2018-04-24": [
                    {
                        "id": "5vj9t1i5B4J3",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "um7UeNPJuAcv",
                        "show_time": "20:00:00"
                    }
                ],
                "2018-04-25": [
                    {
                        "id": "AbS69J4SM4gG",
                        "show_time": "17:00:00"
                    },
                    {
                        "id": "gKax9RXMLozN",
                        "show_time": "20:00:00"
                    }
                ]
            }
        }
    ]
}

这是我尝试过的代码:

 _ = URLSession.shared.dataTask(with: request) { (Data, response, error) in
            if Data != nil{
                do{

                    let access = try JSONSerialization.jsonObject(with: Data!, options: []) as! [String: Any]
                   // print(access)
                    if let data = access["data"] as? [[String:Any]]{
                        if let id = data[0]["id"] as? String{
                            global.showID = id
                          //  print(data)
                        }
                        var j = 0
                        for l in 0..<data.count{
                        if let instances = data[l]["instances"] as? [String:Any] {
                            print(instances)
                            for (key,obj) in instances{
                                //for (key,obj) in (instances as [String:Any]){
                                //print(key)
                                var showDetails: [ShowData] = [ShowData]()
                                if let timeObj = obj as? [[String: Any]]{
                                    var k = 0
                                    for i in 0..<timeObj.count{
                                        let showTime = timeObj[i]["show_time"]
                                        //print(showTime!)

                                        let showID = timeObj[i]["id"]
                                        //print(showID!)

                                        let a = ShowData.init(showId: showID as! String, showtime: showTime as! String)
                                        showDetails.insert(a, at: k)
                                        //print(showDetails)
                                        k += 1
                                    }
                                }
                                let a = Shows(date: key , instance: showDetails)
                                self.showsDate?.insert(a, at: j)
                                //print(self.showsDate!)
                                j += 1
                            }
                            Completion(self.showsDate!)
                        }
                        }
                    }
                }catch let e{
                    print(e)
                }
            }
            }.resume()
  

打印(实例)当我打印时,输出是:

["2018-04-25": <__NSArrayI 0x143bd1ac0>(
{
    id = AbS69J4SM4gG;
    "show_time" = "17:00:00";
},
{
    id = gKax9RXMLozN;
    "show_time" = "20:00:00";
}
)
, "2018-04-24": <__NSArrayI 0x143b3aca0>(
{
    id = 5vj9t1i5B4J3;
    "show_time" = "17:00:00";
},
{
    id = um7UeNPJuAcv;
    "show_time" = "20:00:00";
}
)
, "2018-04-23": <__NSArrayI 0x143be0ce0>(
{
    id = AGciEXINppMe;
    "show_time" = "17:00:00";
},
{
    id = YbKFBJV67hFW;
    "show_time" = "20:00:00";
}
)
, "2018-04-21": <__NSArrayI 0x143b349c0>(
{
    id = DcVQhohv9C3W;
    "show_time" = "17:00:00";
},
{
    id = bZOUk3AT6TMM;
    "show_time" = "20:00:00";
}
)
, "2018-04-22": <__NSArrayI 0x143b24290>(
{
    id = 5YJAydTua6b2;
    "show_time" = "17:00:00";
},
{
    id = qKGXgWvV0r38;
    "show_time" = "20:00:00";
}
)
, "2018-04-20": <__NSArrayI 0x143bd5430>(
{
    id = WRK81ahlWcZZ;
    "show_time" = "17:00:00";
},
{
    id = cDqZjYKHP2xt;
    "show_time" = "20:00:00";
}
)
]

日期与响应中的日期不一致。

2 个答案:

答案 0 :(得分:1)

Dictionary不保持关键订单。

让我们从一些基本数据开始......

struct ShowData: CustomStringConvertible {
    var id: String
    var time: String

    var description: String {
        return "id = \(id); time = \(time)"
    }
}

var rawData: [String: [ShowData]] = [:]

rawData["2018-04-20"] = [
    ShowData(id: "WRK81ahlWcZZ", time: "17:00:00"),
    ShowData(id: "cDqZjYKHP2xt", time: "20:00:00")]
rawData["2018-04-21"] = [
    ShowData(id: "DcVQhohv9C3W", time: "17:00:00"),
    ShowData(id: "bZOUk3AT6TMM", time: "20:00:00")]
rawData["2018-04-22"] = [
    ShowData(id: "5YJAydTua6b2", time: "17:00:00"),
    ShowData(id: "qKGXgWvV0r38", time: "20:00:00")]
rawData["2018-04-23"] = [
    ShowData(id: "AGciEXINppMe", time: "17:00:00"),
    ShowData(id: "YbKFBJV67hFW", time: "20:00:00")]
rawData["2018-04-24"] = [
    ShowData(id: "5vj9t1i5B4J3", time: "17:00:00"),
    ShowData(id: "um7UeNPJuAcv", time: "20:00:00")]
rawData["2018-04-25"] = [
    ShowData(id: "AbS69J4SM4gG", time: "17:00:00"),
    ShowData(id: "AbS69J4SM4gG", time: "20:00:00")]

for key in rawData.keys {
    print(key)
}

对我来说,打印出来......

2018-04-25
2018-04-24
2018-04-23
2018-04-21
2018-04-20
2018-04-22

现在,您可以查找OrderedDictionary或者您可以Map数组的键并对数组进行排序,这样可以将向量返回到Dictionary

或者,您可以对Entry ...

Dictionary数据进行排序
let sorted = rawData.sorted { (lhs, rhs) -> Bool in
    return lhs.key < rhs.key
}

for entry in sorted {
    print(entry.key)
}

哪些输出......

2018-04-20
2018-04-21
2018-04-22
2018-04-23
2018-04-24
2018-04-25

现在,要记住的重要事项是,这仅仅是String比较,但是您正在处理日期。就个人而言,我讨厌处理String日期/时间值,并且我尽快转换为实际用途的东西......

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd"

let actuallySortedByDate = rawData.sorted { (lhs, rhs) -> Bool in
    return formatter.date(from: lhs.key)! < formatter.date(from: rhs.key)!
}

for entry in sorted {
    print(entry.key)
}

哪些输出......

2018-04-20
2018-04-21
2018-04-22
2018-04-23
2018-04-24
2018-04-25

虽然这可能与第一次排序没有任何不同,但执行的比较对数据类型(日期对象)更实际。

重要

这是一个想法的示范。理解密钥无效且Date转换失败是非常重要的。就个人而言,我更倾向于rawData键入Date,而不是String因为它允许更早发现问题。我已经使用了#34;强行打开&#34;在纯粹用于演示的示例中 - 您应该事先验证密钥并确保数据正确

警告:映射Dictionary中的密钥实际上要比它看起来要困难得多。您可以查看What's the cleanest way of applying map() to a dictionary in Swift?了解更多详情。需要少说,使用Swift 4!

好的,这样做的目的是将原来的[String: ShowData] Dictionary转换为[Date: ShowData] Dictionary,这样可以让您处理这种可能性无效的String个密钥。

enum ParserError: Error {
    case invalidDateFormat
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd"
do {
    let mapped = try Dictionary(uniqueKeysWithValues: rawData.map({ (entry) throws -> (Date, [ShowData]) in
        guard let date = formatter.date(from: entry.key) else {
            throw ParserError.invalidDateFormat
        }
        return (Calendar(identifier: .gregorian).startOfDay(for: date), entry.value)
    }))

    let actuallySortedByDate = mapped.sorted { (lhs, rhs) -> Bool in
        return lhs.key < rhs.key
    }

    for entry in actuallySortedByDate {
        print(entry.key)
    }
} catch let error {
    print(error)
}

这最终会打印出来:

2018-01-19 13:00:00 +0000
2018-01-20 13:00:00 +0000
2018-01-21 13:00:00 +0000
2018-01-22 13:00:00 +0000
2018-01-23 13:00:00 +0000
2018-01-24 13:00:00 +0000

ps:我们的想法是尝试将时间分量排除在等式之外

答案 1 :(得分:0)

字典无序。您还会发现处理变量键(您的日期)也很棘手。您应该使instances成为数组并将日期放在字典值中。

如果你这样做,那么你可以制作一些采用struct的{​​{1}}并将你的JSON解析减少到1行