JSON 数据 returns 带数组名称的项目名称

JSON data returns project name with array name

我有这类数据。

John Tylor  :  [StudentData.moreDetailsArray(type: "Full Time", status: "Graduated")]

我只想打印 John Tylor : Full Time : Graduated 而不是打印项目名称和数组键。

代码附在下面:

struct StudentData: Decodable {

    let moreDetails: [moreDetailsArray]
    let id: Int
    let name: String

}

struct moreDetailsArray: Decodable {

    let type: String
    let status: String

}

func parseStudentData(){

        let url = URL(string: "https://api.myjson.com/bins/11mamq")

        URLSession.shared.dataTask(with: url!) { (data, response, error) in
            do{
                if error == nil{
                    let json = try? JSONDecoder().decode([StudentData].self, from: data!)

                    for a in json! {
                        print("\(a.name)"  ," : ",  "\(a.moreDetails)")
                    }

                }
            } catch {
                print("error getting status: \(error)")
            }
        }.resume()
    }
}

您正在尝试 print 建模。您需要 print 每个 属性 您的 moreDetailsArray 模型。

代码:

print("\(a.name)"  ," : ",  "\(a.moreDetails.first!.type)" , " : ", "\(a.moreDetails.first!.status)")

或者你可以不展开并在一个字符串中打印:

if let type = a.moreDetails.first?.type, let status = a.moreDetails.first?.status {
    print("\(a.name) : \(type) : \(status)")
}

并且您应该按照其他答案中所述重命名您的模型对象。这对您的代码可读性和质量有好处。

我认为 moreDetailsArray 不需要是数组。

我会这样实现:

struct Student: Decodable, CustomStringConvertible {
    let id: Int
    let name: String
    let moreDetail: StudentoreDetail

    var description: String {
        return "\(name) : \(additionalInformation.description)"
    }
}

struct StudentAdditionalInfo: Decodable, CustomStringConvertible {
    let type: String
    let status: String

    var description: String {
        return "\(type) : \(status)"
    }
}

那么您需要做的就是:

guard let data = data, 
    let students = try? JSONDecoder().decode([Student].self, from: data) else {

     print("[DEBUG] - No data/json"
     return
} 

for student in students {
    print(student.description)
}

如果您的 moreDetails 实际上是一个数组,您可以 select 第一项(如果存在)。

struct Student: Decodable, CustomStringConvertible {
    let id: Int
    let name: String
    let moreDetail: StudentMoreDetail

    var description: String {
        return "\(name) : \(moreDetail.first?.description)"
    }
}

其他提示:

  1. 不要强制展开,即 JSONDecoder().decode([StudentData].self, from: data**!**)
  2. 以正确的大小写(首字母大写)命名新类型,例如 类、结构、枚举等
  3. 尝试遵循黄金路径,守卫声明可以在这里帮助你。
  4. 不要命名像 moreDetailsArray 这样的东西,它是一个结构而不是一个数组,尽管你在数组中使用它

假设您需要将 moreDetails 保存为一个数组,并且只对数组中的第一项感兴趣:

print("\(a.name) : \(a.moreDetails[0].type) : \(a.moreDetails[0].status)")

此外,您命名为 moreDetailsArray 的结构并不是真正的数组。然而,用于存储它的 属性 是一个数组。所以我建议您改为调用 moreDetails 属性 moreDetailsArray,并将结构的名称更改为 MoreDetails.

像使用 Codable 协议那样创建模型

import Foundation

typealias Students = [Student]

struct Student: Codable {
    let id: Int
    let name: String
    let moreDetails: [MoreDetail]
}

struct MoreDetail: Codable {
    let type, status: String
}

// MARK: Convenience initializers

extension Student {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Student.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

}

extension Array where Element == Students.Element {
    init(students  data: Data) throws {
        self = try JSONDecoder().decode(Students.self, from: data)
    }
}

这样使用:

   func parseStudentData(){

        let url = URL(string: "https://api.myjson.com/bins/11mamq")

        URLSession.shared.dataTask(with: url!) { (data, response, error) in

            if let data = data , let students =  try? Array.init(students: data){
                students.forEach({ (student) in
                    if student.moreDetails.count > 0{
                        print("\(student.name) : \(student.moreDetails[0].type) : \(student.moreDetails[0].status)")
                    }else{
                        print(student.name)
                    }
                })
            }
        }.resume()

    }