Разбор JSON любого типа с Codable - PullRequest
0 голосов
/ 09 ноября 2019

Прошу прощения, если на этот вопрос ответили много раз, но я ищу свою собственную проблему с json, поэтому я пишу это: это мой json, это список уведомлений в массиве, и в дополнительном объекте вы можете видеть, что он имеет объект контракта. , Теперь этот объект меняется, это может быть кампания или обратная связь во 2-м индексе массива json. Как я могу сделать Codable структуру для этого, чтобы декодировать этот тип json Здесь моя структура, я не могу сделать Любой тип в Codable

struct Alert: Decodable { var id: Int? var isUnread: Bool? var userId: Int? var message: String? var notificationType: String? var extra: Any?

 "value": [
        {
            "id": 153,
            "is_unread": true,
            "user_id": 3,
            "message": "Contract offered from JohnWick. Click here to see the details.",
            "notification_type": "Contract",
            "extra": {
                "contract": {
                    "id": 477,
                    "likes": 0,
                    "shares": 0,
                    "account_reach": 0.0,
                    "followers": 0,
                    "impressions": 0.0,
                    "description": "Fsafasd",
                    "budget": 0.0,
                    "start_date": null,
                    "end_date": null,
                    "status": "pending",
                    "is_accepted": false,
                    "brand_id": 443,
                    "influencer_id": 3,
                    "proposal_id": 947,
                    "created_at": "2019-11-09T17:40:57.646Z",
                    "updated_at": "2019-11-09T17:40:57.646Z",
                    "contract_fee": 435345.0,
                    "base_fee": 5000.0,
                    "transaction_fee": 43534.5,
                    "total_fee": 483879.5,
                    "infuencer_completed": false,
                    "brand_completed": false,
                    "comments": 0
                }
            }
        },
{
            "id": 152,
            "is_unread": true,
            "user_id": 3,
            "message": "Message from JohnWick. Click here to check your inbox.",
            "notification_type": "Message",
            "extra": {
                "message": {
                    "id": 495,
                    "body": "Uuhvh",
                    "read": false,
                    "conversation_id": 42,
                    "user_id": 3,
                    "created_at": "2019-11-08T13:44:02.055Z",
                    "updated_at": "2019-11-08T13:44:02.055Z"
                }
            }
        },
    ]

Как вы можете видеть, это может быть сообщение, кампания, контракт или обратная связь, так как я могу проанализировать это или создать модель для этого с CodingKeys Codable

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

Вы не имеете в виду Any здесь. Как вы сказали, extra может быть «сообщением, или кампанией, или контрактом, или обратной связью». Это не может быть UIViewController или CBPeripheral. Это не «ничего». Это одна из четырех вещей.

"Одна из вещей X" - это перечисление:

enum Extra {
    case contract(Contract)
    case campaign(Campaign)
    case message(Message)
    case feedback(Feedback)
}

Чтобы сделать его декодируемым, нам просто нужно найти правильный ключ:

extension Extra: Decodable {
    enum CodingKeys: CodingKey {
        case contract, campaign, message, feedback
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        // Try to decode each thing it could be; throw if nothing matches.
        if let contract = try? container.decode(Contract.self, forKey: .contract) {
            self = .contract(contract)
        } else if let campaign = try? container.decode(Campaign.self, forKey: .campaign) {
            self = .campaign(campaign)
        } else if let message = try? container.decode(Message.self, forKey: .message) {
            self = .message(message)
        } else if let feedback = try? container.decode(Feedback.self, forKey: .feedback) {
            self = .feedback(feedback)
        } else {
            throw DecodingError.valueNotFound(Self.self,
                                              DecodingError.Context(codingPath: container.codingPath,
                                                                    debugDescription: "Could not find extra"))
        }
    }
}
0 голосов
/ 09 ноября 2019

Простым решением было бы создать структуру с именем Extra, имеющую четыре необязательных свойства для каждого из ваших случаев.

struct Extra: Codable {
    let contract: Contract?
    let message: Message?
    let feedback: Feedback?
    let campaign: Campaign?
}

Пока каждое из сообщений, кампании, контракта,и обратная связь имеет фиксированные ответы, тогда вы сможете составить для них структуру, соответствующую Codable.

...