Разбор массива из трех объектов из JSON - PullRequest
0 голосов
/ 02 мая 2018

У меня есть 3 объекта (национальности, услуги и пакеты), и я получил их из ответа JSON как 3 массива этих объектов ... и я хочу проанализировать их из ответа JSON ...

Классы:

struct Root2 : Decodable {
let nationalities : [Nationalities]
let services : [Services]
let packages : [Packages]
}

struct Packages : Decodable {
let id: Int
let name: String
let idService: Int
let nationality: String
let totalPrice: Int
let visitsPerWeek: Int
let excludedDays: String
let excludedShifts: String
let excludedDates: String
let extraVisits: Int
let dateEnabled: String
let dateDisabled: String
let allowedFrom: String
let allowedTo: String
let visitType: String
let createdAt: String?
let updatedAt: String?
 }
 struct Nationalities : Decodable{
let id: Int
let name: String
let createdAt: String?
let updatedAt: String?
}
struct Services : Decodable{
let id: Int
let name, description: String
let createdAt: String?
let updatedAt: String?
}

и у меня есть для каждого другого класса, как:

class Service : NSObject, NSCoding {
var id: Int
var name, desc: String
var createdAt: String?
var updatedAt: String?


init(id: Int, name: String, desc: String) {
    self.id = id
    self.name = name
    self.desc = desc

}

required convenience init(coder aDecoder: NSCoder) {
    let id = aDecoder.decodeInteger(forKey: "id")
    let name = aDecoder.decodeObject(forKey: "name") as! String
    let desc = aDecoder.decodeObject(forKey: "desc") as! String
    self.init(id: id, name: name, desc: desc)
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(id, forKey: "id")
    aCoder.encode(name, forKey: "name")
    aCoder.encode(desc, forKey: "desc")
}

}

и я использую это так:

 func GetServicesPackagesNationalities(){

let link: String = "my link"
guard let url = URL(string: link) else {
    print("Error: cannot create URL")
    return
}
let urlRequest = URLRequest(url: url)

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

let task = session.dataTask(with: urlRequest) {
    (data, response, error) in
    guard error == nil else {
        print("error calling GET on /public/api/services")
        print(error!)
        return
    }
    guard let responseData = data else {
        print("Error: did not receive data")
        return
    }
    do {

        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let result = try decoder .decode(Root2.self, from: responseData)


        var nationalities = [Nationality]()
        for nationality in result.nationalities{
            let newnationality = Nationality(id: nationality.id, name: nationality.name)
            nationalities.append(newnationality)
            print(newnationality.name)
        }


        var services = [Service]()
        for service in result.services {
            let newservice = Service(id: service.id, name: service.name, desc: service.description)
            services.append(newservice)
            print(newservice.name)
        }


       var packages = [Package]()
        for package in result.packages{
            let newpackage = Package(id: package.id, name: package.name, idService: package.idService, nationality: package.nationality, totalPrice: package.totalPrice, visitsPerWeek: package.visitsPerWeek, excludedDays: package.excludedDays, excludedShifts: package.excludedShifts, excludedDates: package.excludedDates, extraVisits: package.extraVisits ,dateEnabled: package.dateEnabled , dateDisabled: package.dateDisabled, allowedFrom: package.allowedFrom, allowedTo: package.allowedTo ,visitType: package.visitType)
            packages.append(newpackage)
            print(newpackage.name)
        }



    }catch  {
        print("error trying to convert data to JSON")
        return
    }
}
task.resume()
 }

и я всегда получу это:

Ошибка при попытке преобразовать данные в JSON

и мой JSON:

   {
"nationalities": [
    {
        "id": 1,
        "name": "Saudi Arabia",
        "created_at": "2018-04-24 05:50:41",
        "updated_at": "2018-04-24 06:35:29",
        "deleted_at": null
    },
    {
        "id": 2,
        "name": "Bahrain",
        "created_at": "2018-04-24 05:52:52",
        "updated_at": "2018-04-24 05:52:52",
        "deleted_at": null
    },
],
"services": [
    {
        "id": 1,
        "name": "Nad",
        "description": "Nad ",
        "created_at": null,
        "updated_at": null,
        "deleted_at": null
    },
    {
        "id": 2,
        "name": "Reay",
        "description": "Re ",
        "created_at": null,
        "updated_at": null,
        "deleted_at": null
    },
],
"packages": [
    {
        "id": 1,
        "name": "Gold Package",
        "id_service": 1,
        "nationality": "4",
        "total_price": 1000,
        "visits_per_week": 2,
        "excluded_weekdays": "null",
        "excluded_shifts": "null",
        "excluded_dates": "1111-11-11",
        "extra_visits": 1,
        "date_enabled_from": "2018-04-01",
        "date_enabled_to": "2018-04-30",
        "date_allowed_from": "2018-04-05",
        "date_allowed_to": "2018-04-30",
        "visit_type": "Multi",
        "created_at": "2018-04-26 11:18:45",
        "updated_at": "2018-04-26 11:18:45",
        "deleted_at": null
    }
]
}

я не знаю, что я делаю неправильно .., так как я попробовал то же самое с двумя объектами и работал нормально ..

Может кто-нибудь сказать мне, что я делаю не так?

используя их в userdefaults:

хранение:

     let userDefaults = UserDefaults.standard


        let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: services)
        userDefaults.set(encodedData, forKey: "services")
        userDefaults.synchronize()

извлечение:

        let decoded  = userDefaults.object(forKey: "services") as! Data
        let decodedService = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Service]

        for service in decodedService {
            print(service.name)
        }

Ответы [ 2 ]

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

Пожалуйста, никогда напечатайте бессмысленную литеральную строку в предложении catch, всегда печатайте фактическую ошибку, она точно говорит вам, что не так

} catch  {
    print(error)
}

В Package много проблем, вот сообщения об ошибках (и предложения по их устранению):

"Нет значения, связанного с ключом CodingKeys (stringValue: \" exclusiveDays \ ", преобразовано в exc__days."

  • В JSON нет ключа excluded_days. Удалить свойство или объявить его необязательным (String?)

"Нет значения, связанного с ключом CodingKeys (stringValue: \" dateEnabled \ ", преобразованным в date_enabled."

  • Фактически преобразованное свойство snake_case должно быть dateEnabledFrom

"Нет значения, связанного с ключом CodingKeys (stringValue: \" dateDisabled \ ", преобразованным в date_disabled."

  • В JSON нет ключа date_disabled. Удалить свойство или объявить его необязательным (String?)

"Нет значения, связанного с ключом CodingKeys (stringValue: \" allowFrom \ ", intValue: nil) (\" allowFrom \ "), преобразовано в allow_from."

  • Фактически преобразованное свойство snake_case должно быть dateAllowedFrom

"Нет значения, связанного с ключом CodingKeys (stringValue: \" allowTo \ ", intValue: nil) (\" allowTo \ "), преобразовано в allow_to."

  • Фактически преобразованное свойство snake_case должно быть dateAllowedTo

Примечание:

Почему вы используете другие дополнительные классы для Nationality, Service, Package? Они кажутся излишними. Если вам действительно нужна ссылочная семантика, декодируйте JSON в классы.

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

См. Разницу между Nationality и Nationalities

Вы должны использовать Nationalities для анализа вашего ответа JSON.

Вы должны сделать это так, как вы объявили Nationalities объект в Root2

var nationalities = [Nationalities]()
for nationality in result.nationalities{
    let newnationality = Nationalities(id: nationality.id, name: nationality.name)
    nationalities.append(newnationality)
    print(newnationality.name)
}

То же самое для Services и Packages, пожалуйста, найдите его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...