1
votes

Extraire et décoder des données JSON à l'aide de Decodable in Swift

J'utilise un framework externe pour afficher la liste des messages et l'écran de détail.

Modèle de message interne du framework que nous ne pouvons pas modifier:

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

Notre réponse API :

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

Comment extraire le tableau msgList de la réponse JSON et le décoder en modèle Message .

Quelque chose comme ne passant que list data / json:

laissez responseMessage = essayer JSONDecoder (). decode ([Message.self], à partir de: liste)

Nous apprécions votre aide et vos suggestions!

Merci


2 commentaires

Quelque chose comme ne transmettre que des données de liste / json . Ce n'est pas possible avec la norme Decodable . Il faut toujours décoder à partir du haut (le dictionnaire avec les données clés) ou écrire une méthode init personnalisée. quicktype.io peut générer les structures pour vous.


Copie possible de Comment décoder une structure JSON imbriquée avec le protocole Swift Decodable?


4 Réponses :


1
votes

Vous devez créer la structure de la charge utile.

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

Décode JSON en utilisant JSONDecoder.

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

    let data: Payload
}

messageList peut accéder en utilisant: responseMessage.data.msgList


0 commentaires

0
votes

Cela devrait être assez facile, mais vous devez décoder l'objet JSON complet à moins que vous ne vouliez commencer à remplacer la méthode init (from decoder :) et à faire certaines choses manuellement.

Essayer d'extraire juste le tableau de messages du JSON serait plus compliqué qu'il n'en vaut la peine.

let messages = result.data.msgList

Vous pouvez accéder aux messages comme ceci:

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


2 commentaires

@LeoDabus comme indiqué dans la question .. "Modèle de Message interne du Framework que nous ne pouvons pas modifier:". La structure Message est définie dans un cadre, pas dans le code des utilisateurs.


pas de soucis leo, il nous manque tous des choses parfois :)



0
votes

Devrait ressembler à quelque chose comme ceci:

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

Ensuite, pour charger vos données:

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

Les noms de classe ne sont qu'un exemple, n'hésitez pas pour les renommer en conséquence.


0 commentaires

0
votes

Vous pouvez essayer

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

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


    }

}


0 commentaires