Данные JSON возвращают имя проекта с именем массива - PullRequest
0 голосов
/ 15 мая 2018

У меня есть данные этого типа.

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 голосов
/ 15 мая 2018

Создать модель, как это, используя 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()

    }
0 голосов
/ 15 мая 2018

Я не думаю, что 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, который был структурой, а не массивом, хотя вы используете его в массиве
0 голосов
/ 15 мая 2018

Предполагая, что вам нужно сохранить moreDetails в виде массива и интересует только первый элемент в массиве:

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

Кроме того, структура, которую вы назвали moreDetailsArray, на самом деле не является массивом.Однако для хранения этого свойства используется массив.Поэтому я бы предложил вместо этого вызвать свойство moreDetails moreDetailsArray и изменить имя структуры на MoreDetails.

0 голосов
/ 15 мая 2018

Вы пытаетесь 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)")
}

И вам следует переименовать объекты вашей модели, как указано в других ответах.Это будет хорошо для вашего кода читаемости и качества.

...