@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.
- Implementing NSCoding does not make the class codable
- You cannot write “init(from decoder: Decoder) throws” in extension
Ways
- Remove the property from CodingKeys. -> for Category
- Call custom initializer of the class customizing decoding initializer -> for Brand
- 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)
}
}
}