Codable Class Does Not Conform to Protocol Decodable

Custom Struct: Type does not conform to protocol 'Decodable'

You will need to make Wish adopt Codable.

But because UIImage and UIColor are not Codable, you’ll have to manually implement them as outlined in Encoding and Decoding Custom Types:

struct Wishlist: Codable {
var name: String
var image: UIImage
var wishes: [Wish]
var color: UIColor
var textColor: UIColor
var index: Int

enum CodingKeys: String, CodingKey {
case name, image, wishData, color, textColor, index
}

init(name: String, image: UIImage, wishes: [Wish], color: UIColor, textColor: UIColor, index: Int) {
self.name = name
self.image = image
self.wishes = wishes
self.color = color
self.textColor = textColor
self.index = index
}

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

name = try values.decode(String.self, forKey: .name)
wishes = try values.decode([Wish].self, forKey: .wishData)
color = try values.decode(Color.self, forKey: .color).uiColor
textColor = try values.decode(Color.self, forKey: .textColor).uiColor
index = try values.decode(Int.self, forKey: .index)

let data = try values.decode(Data.self, forKey: .image)
guard let image = UIImage(data: data) else {
throw DecodingError.dataCorruptedError(forKey: .image, in: values, debugDescription: "Invalid image data")
}
self.image = image
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(name, forKey: .name)
try container.encode(wishes, forKey: .wishData)
try container.encode(Color(uiColor: color), forKey: .color)
try container.encode(Color(uiColor: textColor), forKey: .textColor)
try container.encode(index, forKey: .index)
try container.encode(image.pngData(), forKey: .image)
}

}

struct Wish: Codable {
public var name: String
public var checkedStatus: Bool
public var link: String
public var price: String
public var note: String
public var image: UIImage

init(name: String, link: String, price: String, note: String, image: UIImage, checkedStatus: Bool) {
self.name = name
self.checkedStatus = checkedStatus
self.link = link
self.price = price
self.note = note
self.image = image
}

enum CodingKeys: String, CodingKey {
case name, checkedStatus, link, price, note, image
}

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

name = try values.decode(String.self, forKey: .name)
checkedStatus = try values.decode(Bool.self, forKey: .checkedStatus)
link = try values.decode(String.self, forKey: .link)
price = try values.decode(String.self, forKey: .price)
note = try values.decode(String.self, forKey: .note)

let data = try values.decode(Data.self, forKey: .image)
guard let image = UIImage(data: data) else {
throw DecodingError.dataCorruptedError(forKey: .image, in: values, debugDescription: "Invalid image data")
}
self.image = image
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(name, forKey: .name)
try container.encode(checkedStatus, forKey: .checkedStatus)
try container.encode(link, forKey: .link)
try container.encode(price, forKey: .price)
try container.encode(note, forKey: .note)
try container.encode(image.pngData(), forKey: .image)
}
}

Where I’d use this as a convenient way to encode UIColor objects:

struct Color: Codable {
let red: CGFloat
let green: CGFloat
let blue: CGFloat
let alpha: CGFloat

init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
}

init(uiColor: UIColor) {
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0

uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
}

var uiColor: UIColor { UIColor(red: red, green: green, blue: blue, alpha: alpha) }
}

Note, I did a couple of unrelated changes:

  • I made both of these struct. I wouldn’t introduce reference types (much less NSObject subclasses) unless necessary.

  • I simplified some of the property names. E.g. in Wish, we wouldn’t generally use wish prefix in property names. I also wouldn’t use “data” in a property name unless it was, in fact, a Data.

  • I updated init methods to use standard naming conventions.

Codable class does not conform to protocol Decodable


Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message

It's either because Publication isn't Decodable (you have not shown what it is, so it's hard to tell) or because of the weak designation on publication.

Either way, it's easy to fix: you just need to implement init(from:) to complete the implementation of Decodable; the compiler is simply telling you that this implementation cannot be synthesized.

Codable class doesn't conform to protocol 'Decodable'

It is not necessary to separate the structs. The error occurs because you have added too many keys in the CodingKeys enum. If you keep only the required ones, then it will work:

struct Model: Codable {
let aps: Aps
let link: String?
let checkAction: String?

enum CodingKeys: String, CodingKey {
case aps ,link
case checkAction = "gcm.notificaiton.check_action"
}

struct Aps: Codable {
let alert: Alert
let sound: String?


struct Alert: Codable {
let title: String?
let body: String?
}
}
}

alert, sound etc are not coding keys of Model. They are coding keys of Aps. It is not necessary to specify them in Aps, because they are the same as the property names.

My structure does not conform to protocol 'Decodable' / 'Encodable' if I use protocol type in my structure in swift

JSONDecoder needs to know the concrete type of thing that you want to decode the JSON into. After all, everything must have a concrete type at runtime, that you can get with type(of:). You can't tell it to just "decode a protocol". The encoder is a bit different though - it doesn't actually need to know the concrete type, and there is a way to get around it.

It seems like the type of UIConfig depends on objectid, so we can check objectid and decide what type of UIConfig to decode:

enum CodingKeys: CodingKey {
case id, objectid, config
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
objectid = try container.decode(String.self, forKey: .objectid)
if objectid == "bd_label" {
config = try container.decode(LabelConfig.self, forKey: .config)
} else if objectid == "bd_button" {
config = try container.decode(ButtonConfig.self, forKey: .config)
}
// other cases...
else {
throw DecodingError.dataCorruptedError(forKey: .config, in: container, debugDescription: "no suitable config type found for objectid \(objectid)!")
}
}

For the Encodable part, you can make a "type eraser"-like thingy:

struct AnyEncodable: Encodable {
let encodeFunction: (Encoder) throws -> Void

init(_ encodable: Encodable) {
encodeFunction = encodable.encode(to:)
}

func encode(to encoder: Encoder) throws {
try encodeFunction(encoder)
}
}

and do:

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(objectid, forKey: .objectid)
try container.encode(AnyEncodable(config), forKey: .config)
}

By using AnyEncodable, we are basically wrapping the protocol in a concrete type, but don't worry - this won't actually create an extra pair of curly brackets in the JSON.

Type does not conform to protocol 'Decodable'/'Encodable'

Every property in a Codable type must also be Codable as well.

The simplest way to make a type codable is to declare its properties
using types that are already Codable.

  1. Built-in Codable types — String, Int, Double, Data, URL Array,

  2. Dictionary, Optional are Codable if they contain Codable types

Hence, the AdditionalCharge must also be Codable for FundingRequest to be Codable.

class AdditionalCharge: Codable {
var ItemDescription = ""
var ItemValue:String = ""
}

does not conform to protocol Decodable / Codable

Everything needs to be Codable. So far your Weight struct is not Codable. Update Weight to be Codable as well and then Item will be Codable.

My structure does not conform to protocol 'Decodable' / 'Encodable'

In order for a class or a struct to conform to a protocol, all properties of that class or struct must conform to the same protocol.

UIImage does not conform to Codable, so any class or struct that has properties of type UIImage won’t conform as well. You can replace the image with image data or the image’s base64 representation (as String).

I’ll show you the first option. I suppose you don’t want to write those if lets every time, so let’s add two little extensions to UIImage and Data that will speed up future conversions.

extension UIImage {
var data: Data? {
if let data = self.jpegData(compressionQuality: 1.0) {
return data
} else {
return nil
}
}
}

extension Data {
var image: UIImage? {
if let image = UIImage(data: self) {
return image
} else {
return nil
}
}
}

Change reminderItem’s type from UIImage to Data.

From now on, when you need to access the image, write something like imageView.image = reminderGroup.reminderItem.image. And when you need to save an instance of UIImage to reminderItem, write something like reminderGroup.reminderItem = image.data! (the bang operator (exclamation mark) is needed because the computed property data is optional).

Also make sure ReminderItem does conform to Codable. You didn’t provide the declaration of that type, so I can’t say whether it conforms of not.

Type 'PlayerData' does not conform to protocol 'Decodable' and 'Encodable'

Player should conform also

class Player : Codable {


Related Topics



Leave a reply



Submit