Извлечение и декодирование данных JSON с использованием Decodable в Swift - PullRequest
1 голос
/ 25 сентября 2019

Я использую внешнюю платформу для отображения списка сообщений и подробного экрана.

Внутренняя модель сообщения, которую мы не можем изменить:

public struct Message: Decodable, Encodable {
    public var id: String?
    public var title: String?
    public var subTitle: String?
    public var status: String?
}

Наш ответ API:

{ 
   "data":{ 
      "custId":"1234",
      "type":"premium",
      "totalCount":"100",
      "msgList":[ 
         { 
            "id":"1",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         },
         { 
            "id":"2",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         }
      ],
      "categoryCount":"50"
   }
}

Как мне извлечь msgList массив из ответа JSON и декодировать в Message модель.

Что-то вроде только передачи list data / json:

let responseMessage = попробовать JSONDecoder (). Decode ([Message.self], from: list)

Благодарим Вас за помощь и предложение!

Спасибо

Ответы [ 4 ]

0 голосов
/ 25 сентября 2019

Можно попробовать

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let str = """

{
   "data":{
      "custId":"1234",
      "type":"premium",
      "totalCount":"100",
      "msgList":[
         {
            "id":"1",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         },
         {
            "id":"2",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         }
      ],
      "categoryCount":"50"
   }
}
"""

        do {

            let res = try JSONDecoder().decode(Root.self, from:Data(str.utf8))

            print(res.list)
        }
        catch {

            print(error)
        }


    }

}

struct Root : Decodable {
    let list : [Message]
    struct AnyCodingKey : CodingKey {
        var stringValue: String
        var intValue: Int?
        init(_ codingKey: CodingKey) {
            self.stringValue = codingKey.stringValue
            self.intValue = codingKey.intValue
        }
        init(stringValue: String) {
            self.stringValue = stringValue
            self.intValue = nil
        }
        init(intValue: Int) {
            self.stringValue = String(intValue)
            self.intValue = intValue
        }
    }
    init(from decoder: Decoder) throws {
        var con = try! decoder.container(keyedBy: AnyCodingKey.self)
        con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"data"))
        let res = try! con.decode([Message].self, forKey: AnyCodingKey(stringValue:"msgList"))
        self.list = res       
    }
}


struct Message: Codable {
    let id,title,subTitle,status: String? 
}
0 голосов
/ 25 сентября 2019

Это должно быть довольно просто, но вам нужно декодировать полный объект JSON, если вы не хотите начинать переопределять метод init(from decoder:) и делать что-то вручную.

Попытка извлечь только массив сообщений изJSON будет больше хлопот, чем стоит.

import UIKit

let jsonData = """
{
   "data":{
      "custId":"1234",
      "type":"premium",
      "totalCount":"100",
      "msgList":[
         {
            "id":"1",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         },
         {
            "id":"2",
            "title":"Main Title",
            "subTitle":"Sub title",
            "status":"R"
         }
      ],
      "categoryCount":"50"
   }
}
""".data(using: .utf8)

struct Root: Decodable {
    let data: Customer
}

struct Customer: Decodable {
    let custId: String
    let type: String
    let totalCount: String
    let msgList: [Message]
}

public struct Message: Decodable, Encodable {
    public var id: String?
    public var title: String?
    public var subTitle: String?
    public var status: String?
}

do {
    let result = try JSONDecoder().decode(Root.self, from: jsonData!)
    print(result)
} catch {
    print(error)
}

Вы можете получить доступ к следующим сообщениям:

let messages = result.data.msgList
0 голосов
/ 25 сентября 2019

Должно выглядеть примерно так:

// MARK: - Root
struct Root: Codable {
    let data: DataClass
}

// MARK: - DataClass
struct DataClass: Codable {
    let custID, type, totalCount: String
    let msgList: [MsgList]
    let categoryCount: String

    enum CodingKeys: String, CodingKey {
        case custID = "custId"
        case type, totalCount, msgList, categoryCount
    }
}

// MARK: - MsgList
struct MsgList: Codable {
    let id, title, subTitle, status: String
}

Затем для загрузки ваших данных:

let list: [String : Any] = [:] // load data accordingly...
if let responseMessage = try JSONDecoder().decode(Root.self, from: list)
{
    // responseMessage.data.msgList
}

Имена классов являются лишь примером, не стесняйтесь переименовать их соответственно.

0 голосов
/ 25 сентября 2019

Необходимо создать структуру полезной нагрузки.

struct Data: Decodable {
    struct Payload: Decodable {
        let msgList: [Message]
    }

    let data: Payload
}

Декодировать JSON с помощью JSONDecoder.

let responseMessage = try JSONDecoder().decode([Message.self], from: list)

messageList может получить доступ с помощью: responseMessage.data.msgList

...