快速使用Decodable提取和解码JSON数据

时间:2019-09-25 09:22:16

标签: ios json swift decodable

我正在使用一个外部框架来显示消息列表和详细信息屏幕。

我们无法修改的框架内部消息模型:

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"
   }
}

如何从JSON响应中提取msgList数组并解码为Message模型。

有点像只传递list data / json:

  

let responseMessage =试试JSONDecoder()。decode([Message.self],来自:   列表)

感谢您的帮助和建议!

谢谢

4 个答案:

答案 0 :(得分:0)

您必须创建有效负载结构。

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

    let data: Payload
}

使用JSONDecoder解码JSON。

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

messageList可以使用:responseMessage.data.msgList

答案 1 :(得分:0)

这应该很容易,但是除非您要开始覆盖init(from decoder:)方法并手动执行一些操作,否则您需要解码整个JSON对象。

尝试仅从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

答案 2 :(得分:0)

应该看起来像这样:

// 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
}

类名只是一个例子,请随时对它们进行重命名。

答案 3 :(得分:0)

您可以尝试

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? 
}
相关问题