将一个JSON连接到另一个

时间:2019-06-08 19:37:34

标签: ios json swift

我有这两个JSON,它们共享一个字段userId

这个:

{
    "oldest": "2019-01-24T00:00:00+00:00",
    "activities": [
        {
            "message": "<strong>Henrik</strong> didn't resist a guilty pleasure at <strong>Starbucks</strong>.",
            "amount": 2.5,
            "userId": 2,
            "timestamp": "2019-05-23T00:00:00+00:00"
        },
        {
            "message": "<strong>Johan</strong> made a roundup.",
            "amount": 0.32,
            "userId": 3,
            "timestamp": "2019-05-22T00:00:00+00:00"
        },
        {
            "message": "<strong>You</strong> didn't resist a guilty pleasure at <strong>Starbucks</strong>.",
            "amount": 15,
            "userId": 1,
            "timestamp": "2019-05-21T00:00:00+00:00"
        }
]

还有一个:

[
    {
        "userId": 1,
        "displayName": "Mikael",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/mikael.jpg"
    },
    {
        "userId": 2,
        "displayName": "Henrik",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/henrik.jpg"
    },
    {
        "userId": 3,
        "displayName": "Johan",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/johan.jpg"
    },
    {
        "userId": 4,
        "displayName": "Erik",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/erik.jpg"
    },
    {
        "userId": 5,
        "displayName": "George",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/george.jpg"
    },
    {
        "userId": 6,
        "displayName": "Daniel",
        "avatarUrl": "http://qapital-ios-testtask.herokuapp.com/avatars/daniel.jpg"
    }
]

现在我有第一个这样整理出来的:

struct Root: Decodable {
    var oldest: Date
    var activities: [Activity]
}

struct Activity: Decodable {
    var message: String
    var amount: Float
    var userId: Int
    var timestamp: Date
}

请注意,Activity(第一个JSON)中的userId变量也出现在第二个JSON上。我正在使用这些结构填充我的TableViewController

我最终需要在消息和日期标签(检查图像)旁边显示头像图像。为此,我认为我需要将第一个JSON与第二个JSON连接/关联(不知道这个词),如果我错了,请更正我。我还需要User的另一个结构吗?

这是我的联网代码:

let userJSONURLString = "https://qapital-ios-testtask.herokuapp.com/users"
        let activitiesJSONURLString = "https://qapital-ios-testtask.herokuapp.com/activities?from=2016-05-23T00:00:00+00:00&to=2019-05-23T00:00:00+00:00"
        guard let userURL = URL(string: userJSONURLString) else { return }
        guard let activitiesURL = URL(string: activitiesJSONURLString) else { return }

        URLSession.shared.dataTask(with: activitiesURL) { (data, response, err) in
            // perhaps check err
            // also perhaps check response status 200 OK

            guard let data = data else { return }

            do {
                // Activities
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .iso8601
                let result = try decoder.decode(Root.self, from: data)
                self.activities = result.activities

                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            } catch {
                print("Error serializing json: ", error)
            }

        }.resume()

这是我的cellForRowAt(如果需要):

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ActivityCell", for: indexPath) as! MainTableViewCell
        let activity = activities[indexPath.row]

        // Amount
        cell.amountLabel.text = String(format: "$%.2f", activity.amount)

        // Message
        let formattedString = activity.message.htmlAttributedString().with(font:UIFont(name: "Helvetica Neue", size: 15)!)
        cell.descriptionLabel.attributedText = formattedString

        // Date
//        cell.dateLabel

        // Avatar


        return cell
    }

更新的代码:

struct Activity: Decodable {
    var message: String
    var amount: Float
    var userId: Int
    var timestamp: Date
    var avatar : UIImage = UIImage(named: "user-icon-image-placeholder-300-grey.jpg")!
    private enum CodingKeys : String, CodingKey { case message, amount, userId, timestamp }
}

URLSession.shared.dataTask(with: activitiesURL) { (data, response, err) in
            guard let data = data else { return }
            do {
                // Activities
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .iso8601
                let result = try decoder.decode(Root.self, from: data)
                self.activities = result.activities

                URLSession.shared.dataTask(with: userURL) { (data, response, err) in
                    guard let data = data else { return }
                    do {
                        // Users
                        let usersJson = try JSONSerialization.jsonObject(with: data, options: [])
                        guard let jsonArray = usersJson as? [[String: Any]] else { return }

                        for dic in jsonArray {
                            guard let avatarUrl = dic["avatarUrl"] as? String else { return }
                            print(avatarUrl)
                        }

                    } catch {
                        print("Error serializing json: ", error)
                    }
                    }.resume()
            } catch {
                print("Error serializing json: ", error)
            }

            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }.resume()

1 个答案:

答案 0 :(得分:0)

  • Activity结构中添加CodingKeys和化身URL的额外成员

    struct Activity: Decodable {
        let message: String
        let amount: Float
        let userId: Int
        let timestamp: Date
    
        var avatar : URL = // some default URL to a placeholder image on disk
    
        private enum CodingKeys : String, CodingKey { case message, amount, userId, timestamp }
    } 
    

    CodingKeys的目的是仅对前4个结构成员进行解码。

  • 在第一个数据任务的完成处理程序中,添加第二个数据任务以加载用户数据。

  • 使用JSONSerialization将JSON解码为字典数组。
  • 在一个循环中,获取给定userId的活动并更新头像URL。
  • 然后重新加载表格视图。
  • 要加载头像图像,您需要一种逻辑来异步下载和缓存图像。