Как обрабатывать пустой массив в кодируемом процессе декодирования

Хорошо работает, когда массив «адресов» не пустой. Но это не удается, когда массив «адресов» пуст. Любая помощь будет принята с благодарностью. У меня есть структура для объекта Address. В основном «адрес» - это массив объектов типа «Адрес», но когда адрес пуст, он не работает.

{
    "success": "1",
    "message": "You have succesfully verified your mobile no",
    "details": {
        "customer_id": 825,
        "is_delivery_available": "0",
        "is_registration_complete": "0",
        "is_customer_verified": "0",
        "customer_status": "0",
        "cart_count": "0",
        "name_type": "mr",
        "firstname": "",
        "lastname": "",
        "full_name": "",
        "pincode": "",
        "profile_pic": "",
        "mobile": "8583846677",
        "email": "",
        "address": [

        ],
        "referral_code": ""
    }
}

Выше представлен JSON, который я пытаюсь декодировать с помощью Codable в Swift4.

import Foundation

struct Signup: Codable {
    var success:String?
    var message:String?
    var details:Details?

    private enum CodingKeys: String, CodingKey { case success, message, details }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        success = try values.decode(String.self, forKey: .success)
        message = try values.decode(String.self, forKey: .message)
        if let _details = try? values.decode(Details.self, forKey: .details) {
            details = _details
        }
    }
}

struct Details: Codable {
    var address:[Address]?
    var cart_count:String?
    var customer_id:String?
    var customer_status:String?
    var email:String?
    var firstname:String?
    var full_name:String?
    var is_customer_verified:String?
    var is_delivery_available:String?
    var is_registration_complete:String?
    var lastname:String?
    var mobile:String?
    var name_type:String?
    var pincode:String?
    var profile_pic:String?
    var referral_code:String?

    private enum CodingKeys: String, CodingKey { case address, cart_count, customer_id, customer_status, email, firstname, full_name, is_customer_verified, is_delivery_available, is_registration_complete, lastname, mobile, name_type, pincode, profile_pic, referral_code }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)

        ****-->>> Issue is in this line. How to handle empty array while decoding. <<<--****
        address = try? values.decode([Address].self, forKey: .address) 

        cart_count = try values.decode(String.self, forKey: .cart_count)
        customer_id = try values.decode(String.self, forKey: .customer_id)
        customer_status = try values.decode(String.self, forKey: .customer_status)
        email = try values.decode(String.self, forKey: .email)
        firstname = try values.decode(String.self, forKey: .firstname)
        full_name = try values.decode(String.self, forKey: .full_name)
        is_customer_verified = try values.decode(String.self, forKey: .is_customer_verified)
        is_delivery_available = try values.decode(String.self, forKey: .is_delivery_available)
        is_registration_complete = try values.decode(String.self, forKey: .is_registration_complete)
        lastname = try values.decode(String.self, forKey: .lastname)
        mobile = try values.decode(String.self, forKey: .mobile)
        name_type = try values.decode(String.self, forKey: .name_type)
        pincode = try values.decode(String.self, forKey: .pincode)
        profile_pic = try values.decode(String.self, forKey: .profile_pic)
        referral_code = try values.decode(String.self, forKey: .referral_code)
    }
}

struct Address: Codable {
    var address_default:String?
    var address_id:String?
    var address_type:String?
    var city:String?
    var customer_id:String?
    var flat_or_house_or_office_no:String?
    var full_address:String?
    var full_name:String?
    var landmark:String?
    var lat:String?
    var lng:String?
    var mobile:String?
    var name_type:String?
    var pincode:String?
    var street_or_society_or_office_name:String?
}

Я застрял в этом. Как обрабатывать пустой массив при декодировании данных json в Swift4 Codable.


person Alok    schedule 24.05.2018    source источник
comment
decodeIfPresent (_: forKey :) метод декодирования   -  person Khushbu    schedule 24.05.2018
comment
CommonResponse: Регистрация (успех: Необязательно (1), сообщение: Необязательно (Вы успешно подтвердили номер своего мобильного телефона), подробности: ноль) - не сработало.   -  person Alok    schedule 24.05.2018


Ответы (2)


Я столкнулся с этой проблемой и решил ее, как показано ниже.

if let _address = try? values.decode([Address].self, forKey: .address) {
    address = _address
} else {
    address = []
}

Вы можете попробовать.

person andrew54068    schedule 18.07.2018
comment
Небольшое улучшение: позвольте _address = попробовать? values.decode ([Адрес] .self, forKey: .address) ?? [] - person Amin Benarieb; 11.01.2021

Настоящая проблема в том, что customer_id в Details это Int, а не String. Расшифровка пустого массива должна работать.

Ваш код слишком сложен. Наслаждайтесь магией Codable и опустите все CodingKeys и инициализаторы и объявите все члены структуры как необязательные и как константы

struct Signup: Decodable {
    let success : String
    let message : String
    let details : Details
}

struct Details : Decodable {
    let address : [Address]
    let cart_count : String
    let customer_id : Int
    let customer_status, email, firstname, full_name : String
    let is_customer_verified, is_delivery_available, is_registration_complete : String
    let lastname, mobile, name_type, pincode, profile_pic, referral_code : String
}

struct Address: Decodable {
    let address_default, address_id, address_type, city, customer_id : String
    let flat_or_house_or_office_no, full_address, full_name : String
    let landmark, lat, lng, mobile, name_type, pincode, street_or_society_or_office_name : String
}

Вы даже можете назвать участников camelCased

let cartCount : String
let customerId : Int
...
let isRegistrationComplete : String

и передать стратегию декодирования ключей convertFromSnakeCase

decoder.keyDecodingStrategy = .convertFromSnakeCase

По-прежнему нет лишнего кода!

person vadian    schedule 18.07.2018
comment
Можете ли вы действительно избавиться от опций, если не уверены, что данные будут там? Мой код не может анализировать пустой массив, как в foo: []. Как мне кодировать? Быстрый шрифт предлагал множество безумных классов и методов. Содержимое массива, если оно не пустое, всегда является строками, однако [String] выдает ошибку typeMismatch (Swift.Array ‹Any›, Swift.DecodingError.Context (codingPath: [], debugDescription: Ожидается декодирование Array ‹Any›, но обнаружено словарь вместо этого., basicError: nil)) - person user6631314; 29.07.2020
comment
@ user6631314 Сообщение об ошибке связано с корневым объектом, а не с конкретным ключом. - person vadian; 29.07.2020