Подключите один JSON к другому - PullRequest
0 голосов
/ 08 июня 2019

У меня есть эти 2 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
}

Обратите внимание, что переменная userId в Activity (1-й JSON) также появляется во 2-м JSON. Я использую эти структуры для заполнения моего TableViewController .

В конечном итоге мне нужно, чтобы изображение аватара отображалось рядом с сообщением и меткой даты (проверьте изображение). Для этого я думаю, что мне нужно было бы соединить / связать (не знаю, как это называется) 1-й JSON со 2-м JSON, поправьте меня, если я ошибаюсь. Мне также нужна другая структура для пользователя?

Это мой сетевой код:

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 голосов
/ 08 июня 2019
  • В структуре 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 структурыэлементы декодируются.

  • В обработчике завершения первой задачи данных добавьте вторую задачу данных для загрузки пользовательских данных.

  • Декодируйте JSON как массив словарей с помощью JSONSerialization.
  • В цикле получите действие для данного userId и обновите URL аватара.
  • Затем перезагрузите представление таблицы.
  • Чтобы загрузить изображения аватара, вам нужна логика для асинхронной загрузки и кэширования изображений.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...