how to make codable class (to use in objective c)

@objc class BlindReason: NSObject, Codable {

let title: String

let reasonDescription: String

init(title: String, reasonDescription: String) {

self.title = title

self.reasonDescription = reasonDescription

}

private enum CodingKeys: String, CodingKey {

case title, reasonDescription = “description”

}

}

 

 

if let data = try? JSONSerialization.data(withJSONObject: blindReasons, options: JSONSerialization.WritingOptions.prettyPrinted) {

let decoder = JSONDecoder()

if let reasons = try? decoder.decode([BlindReason].self, from: data) {

//do something

}

}

}

 

  • When the class has not codable property. like when the property type is custom class written in objective-c.
  1. Implementing NSCoding does not make the class codable
  2. You cannot write “init(from decoder: Decoder) throws” in extension

Ways

  1. Remove the property from CodingKeys. -> for Category
  2. Call custom initializer of the class customizing decoding initializer -> for Brand
    1. It can not decoded as [String: Any] json format. Because you cannot use “Any”(contextual type) decoding

Category.h

@interface Category : NSObject

Brand+extensions.swift

extension Brand {

    enum CodingKeys: String, CodingKey {

        case index

        case name

        case property2

    }

    

    static func decode(brandContainer: KeyedDecodingContainer<BrandItem.CodingKeys>) throws -> BrandItem {

        let index = try brandContainer.decode(Int.self, forKey: .index)

        let name = try brandContainer.decode(String.self, forKey: .name)

        let property2 = try brandContainer.decode(String.self, forKey: .property2)

        let brandDictionary = [“index”: index, “name”: name, “property2”: property2] as [String : Any]

        let brand = Brand(data: brandDictionary)

        return brandItem!

    }

}

Product.swift

class Product: Decodable {

    let index:Int

    var name:String = “”

    var categoryList: [Category] = [Category]()

    

    var brand: Brand = Brand()

    var image: URL!

    

    enum CodingKeys: String, CodingKey {

        case index

        case brand = “brand”

    }

    

    required init(from decoder: Decoder) throws {

        let values = try decoder.container(keyedBy: CodingKeys.self)

        index = try values.decode(UInt.self, forKey: .index)

let brandContainer = try values.nestedContainer(keyedBy: BrandItem.CodingKeys.self, forKey: .brand)

let index = try brandContainer.decode(Int.self, forKey: .index)

        let name = try brandContainer.decode(String.self, forKey: .name)

        let property2 = try brandContainer.decode(String.self, forKey: .property2)

        let brandDictionary = [“index”: index, “name”: name, “alias”: alias] as [String : Any]

        brand = BrandItem(data: brandDictionary)

    }

  • When you have nullable value on JSON and you cannot use optional to work with objective-C

Product.swift

class Product: Decodable {

    var encryptedProductId:String = “”

    let index:UInt

   init(index: UInt) {

        self.index = index

    }

}

Event.swift

@objc class Event: NSObject, Decodable {

    let index: Int

    let product: Product

    

    enum CodingKeys: String, CodingKey {

        case index

        case product

    }

    

    required init(from decoder: Decoder) throws

    {

        let values = try decoder.container(keyedBy: CodingKeys.self)

        index = try values.decode(Int.self, forKey: .index)

        if let tempProduct = try? values.decode(Product.self, forKey: .product) {

            product = tempProduct

        } else {

            product = Product(index: 0)

        }

    }

}

 

 

댓글 남기기