JSON数据返回带有数组名称的项目名称

时间:2018-05-15 12:48:46

标签: arrays json swift dictionary codable

我有这种类型的数据。

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

4 个答案:

答案 0 :(得分:0)

您正在尝试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)")
}

您应该按照另一个答案中的说明重命名模型对象。这对您的代码可读性和质量都有好处。

答案 1 :(得分:0)

我不认为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实际上是一个数组,你可以选择第一个项目(如果存在)。

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命名为结构而不是实际上是数组

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

使用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()

    }