List Is Not Conforming to Encodable

Type 'AreaData' does not conform to protocol 'Encodable'

try this,

 struct AreaDataModel: Codable {
let id, name: String
let parentID: String? // AnyObject can't conform to Encodable protocol .
let sublevel: [Sublevel]

enum CodingKeys: String, CodingKey {
case id = "ID"
case name = "Name"
case parentID = "parentId"
case sublevel
}
}

// MARK: - Sublevel
struct Sublevel: Codable {
let id, name, on, off: String
let parentID: String
let sublevel: [Sublevel]

enum CodingKeys: String, CodingKey {
case id = "ID"
case name = "Name"
case on = "On"
case off = "Off"
case parentID = "parentId"
case sublevel
}
}

typealias AreaData = [AreaDataModel]

I recommend this tool simple and fast .

Why not conform to protocol encodable decodable?

When you define CodingKeys, you need to provide key for each non-optional/non-initialized property so that compiler know how to initialize while decoding. Applying this to Video, it will look like this,

struct Video: Codable {

var title: String
var description: String
var url: URL
var thumbnailImageURL: URL

var numberOfLikes: Int {
return likes.value

}

private var likes: StringBacked<Int>

enum CodingKeys: String, CodingKey{
case title = "xxx"
case description = "jjjj"
case url = "url"
case thumbnailImageURL = "jjjjjjjj"
case likes = "jjjjjkkkk"

}
}

If you see closely, this property private var likes: StringBacked<Int> was not provided any CodingKey in the enum so compiler was complaining. I updated the enum with this case case likes = "jjjjjkkkk" and removed case numberofLikes = "jjjjjkkkk" because numberofLikes is a read only computed property that doesn't need any parsing.

Type 'X' does not conform to protocol 'Encodable'

I google and found an article, which provide implementations for un-codable CLLocation.

After reading that article, it's hard to implement Decodable for CLLocation. But the author use another struct Location for decoding CLLocation object. It's funny and tricky.


For Encodable

extension CLLocation: Encodable {
enum CodingKeys: String, CodingKey {
case latitude
case longitude
case altitude
case horizontalAccuracy
case verticalAccuracy
case speed
case course
case timestamp
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(coordinate.latitude, forKey: .latitude)
try container.encode(coordinate.longitude, forKey: .longitude)
try container.encode(altitude, forKey: .altitude)
try container.encode(horizontalAccuracy, forKey: .horizontalAccuracy)
try container.encode(verticalAccuracy, forKey: .verticalAccuracy)
try container.encode(speed, forKey: .speed)
try container.encode(course, forKey: .course)
try container.encode(timestamp, forKey: .timestamp)
}
}

For Decodable

struct Location: Codable {
let latitude: CLLocationDegrees
let longitude: CLLocationDegrees
let altitude: CLLocationDistance
let horizontalAccuracy: CLLocationAccuracy
let verticalAccuracy: CLLocationAccuracy
let speed: CLLocationSpeed
let course: CLLocationDirection
let timestamp: Date
}
extension CLLocation {
convenience init(model: Location) {
self.init(coordinate: CLLocationCoordinate2DMake(model.latitude, model.longitude), altitude: model.altitude, horizontalAccuracy: model.horizontalAccuracy, verticalAccuracy: model.verticalAccuracy, course: model.course, speed: model.speed, timestamp: model.timestamp)
}
}

///
struct Person {
let name: String
let location: CLLocation
enum CodingKeys: String, CodingKey {
case name
case location
}
}
extension Person: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let name = try values.decode(String.self, forKey: .name)

// Decode to `Location` struct, and then convert back to `CLLocation`.
// It's very tricky
let locationModel = try values.decode(Location.self, forKey: .location)
location = CLLocation(model: locationModel)
}
}

`RLMArray` does not conform to protocol 'Encodable'

Codable is the exact same as Decodable + Encodable. If you want to conform to Codable you will need to implement the encoding functions, which for your Person object would be:

enum CodingKeys: String, CodingKey {
case name
case hobbies
// or: case hobbies = "customHobbiesKey" if you want to encode to a different key
}

func encode(to encoder: Encoder) throws {
do {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(hobbies, forKey: .hobbies)
} catch {
print(error)
}
}

Add this to your Person class, and then implement the same thing for your Hobby class.

Because i'm not sure if you even want to encode: If all you need to do is create Realm-Objects from Json I would simply replace 'Codable' with the'Decodable'-Protocol.

EDIT: I noticed the issue is about the RLMArray. I'm not sure how codable works with RLMArray, but if it doesn't work you could try replacing the declaration with

let hobbies = List<Hobby>()

and then in init() replace the 'hobbies' line with:

let tempHobbyList: [Hobby] = try container.decode([Hobby].self, forKey: .hobbies)
self.hobbies.append(objectsIn: tempHobbyList)

That's how I got my lists with realmObjects to work with codable



Related Topics



Leave a reply



Submit