简体   繁体   中英

How to create JSON Codable and Decodable for a JSON data using Swift?

In myscenario, I am trying to get the data from JSON response with help of Stuct Codable and Decodable. But I am getting below error If I use below code

Error:typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))

Code Below

func jsonDataLoad() {
    if let url = URL(string: "https://api.myjson.com/bins/1e33oo") {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    //Swift 2/3/Objective C
                    //let json = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
                    //print(json)
                    let student = try JSONDecoder().decode(RootElement.self, from: data)
                    print(student.gender)
                } catch let error {
                    print(error)
                }
            }
            }.resume()
    }
}

Codable Structure

// MARK: - RootElement
struct RootElement: Decodable {
    let id, name, gender, welcomeClass: String
    let club, persona, crush, breastSize: String
    let strength, hairstyle, color: String
    let accessory, scheduleTime, scheduleDestination, scheduleAction: String
}

Your json root is an array not a dictionary [RootElement].self

let students = try JSONDecoder().decode([RootElement].self, from: data)
students.forEach {
   print($0.id)
}

Follwoing will be the model to parse your JSON, plus i would highly recommend you the following website to create your json models, instead of trying it yourself to avoid mistakes

https://app.quicktype.io/

import Foundation

// MARK: - JSONModelElement
struct JSONModelElement: Codable {
    let id, name, gender, jsonModelClass: String
    let club, persona, crush, breastSize: String
    let strength, hairstyle, color: String
    let stockings: Stockings
    let accessory, scheduleTime, scheduleDestination, scheduleAction: String

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case gender = "Gender"
        case jsonModelClass = "Class"
        case club = "Club"
        case persona = "Persona"
        case crush = "Crush"
        case breastSize = "BreastSize"
        case strength = "Strength"
        case hairstyle = "Hairstyle"
        case color = "Color"
        case stockings = "Stockings"
        case accessory = "Accessory"
        case scheduleTime = "ScheduleTime"
        case scheduleDestination = "ScheduleDestination"
        case scheduleAction = "ScheduleAction"
    }
}

enum Stockings: String, Codable {
    case loose = "Loose"
    case none = "None"
    case osana = "Osana"
}

typealias JSONModel = [JSONModelElement]

// pasrse the JSON using one single line.

let students = try JSONDecoder().decode(JSONModel.self, from: data)

You can use this code:

func jsonDataLoad() {
    if let url = URL(string: "https://api.myjson.com/bins/1e33oo") {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let students = try? JSONDecoder().decode(ModelAPI.self, from: data)
                    students?.forEach {
                        print($0.id)
                    }
                }
            }
        }.resume()
    }
}

your class:

import Foundation

class ModelAPIElement: Codable {
    let id, name, gender, modelAPIClass: String?
    let club, persona, crush, breastSize: String?
    let strength, hairstyle, color: String?
    let stockings: Stockings?
    let accessory, scheduleTime, scheduleDestination, scheduleAction: String?

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case gender = "Gender"
        case modelAPIClass = "Class"
        case club = "Club"
        case persona = "Persona"
        case crush = "Crush"
        case breastSize = "BreastSize"
        case strength = "Strength"
        case hairstyle = "Hairstyle"
        case color = "Color"
        case stockings = "Stockings"
        case accessory = "Accessory"
        case scheduleTime = "ScheduleTime"
        case scheduleDestination = "ScheduleDestination"
        case scheduleAction = "ScheduleAction"
    }

    init(id: String?, name: String?, gender: String?, modelAPIClass: String?, club: String?, persona: String?, crush: String?, breastSize: String?, strength: String?, hairstyle: String?, color: String?, stockings: Stockings?, accessory: String?, scheduleTime: String?, scheduleDestination: String?, scheduleAction: String?) {
        self.id = id
        self.name = name
        self.gender = gender
        self.modelAPIClass = modelAPIClass
        self.club = club
        self.persona = persona
        self.crush = crush
        self.breastSize = breastSize
        self.strength = strength
        self.hairstyle = hairstyle
        self.color = color
        self.stockings = stockings
        self.accessory = accessory
        self.scheduleTime = scheduleTime
        self.scheduleDestination = scheduleDestination
        self.scheduleAction = scheduleAction
    }
}

enum Stockings: String, Codable {
    case loose = "Loose"
    case none = "None"
    case osana = "Osana"
}

typealias ModelAPI = [ModelAPIElement]

updated: or struct

import Foundation

struct ModelAPIElement: Codable {
    let id, name, gender, modelAPIClass: String?
    let club, persona, crush, breastSize: String?
    let strength, hairstyle, color: String?
    let stockings: Stockings?
    let accessory, scheduleTime, scheduleDestination, scheduleAction: String?

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case gender = "Gender"
        case modelAPIClass = "Class"
        case club = "Club"
        case persona = "Persona"
        case crush = "Crush"
        case breastSize = "BreastSize"
        case strength = "Strength"
        case hairstyle = "Hairstyle"
        case color = "Color"
        case stockings = "Stockings"
        case accessory = "Accessory"
        case scheduleTime = "ScheduleTime"
        case scheduleDestination = "ScheduleDestination"
        case scheduleAction = "ScheduleAction"
    }
}

enum Stockings: String, Codable {
    case loose = "Loose"
    case none = "None"
    case osana = "Osana"
}

typealias ModelAPI = [ModelAPIElement]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM