Duck
Duck

Reputation: 36003

Trying to make a class codable in Swift but it is not the correct format?

I am creating a class that conforms to codable.

I have this:

import Foundation

class Attribute : Decodable {

  var number: Int16
  var label: String?
  var comments: String?

  init(number:Int16, label:String?, comments:String?) {
    self.number = number
    self.label = label
    self.comments = comments
  }

  // Everything from here on is generated for you by the compiler
  required init(from decoder: Decoder) throws {
    let keyedContainer = try decoder.container(keyedBy: CodingKeys.self)
    number = try keyedContainer.decode(Int16.self, forKey: .number)
    label = try keyedContainer.decode(String.self, forKey: .label)
    comments = try keyedContainer.decode(String.self, forKey: .comments)
  }

  enum CodingKeys: String, CodingKey {
    case number
    case label
    case comments
  }

}

extension Attribute: Encodable {

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(number, forKey: .number)
    try container.encode(label, forKey: .label)
    try container.encode(comments, forKey: .comments)
  }
}

This is apparently fine.

I create an instance of Attribute and encode it using:

  let newAttribute = Attribute.init(number:value.number, label:value.label, comments:value.shortcut)

Then I create an array of these attributes and encode that array using

  let array = try JSONEncoder().encode(array)

This will encode the array of Attribute to Data.

Then I try to convert the Data object back to the array of Attribute using this:

let array = try JSONDecoder().decode(Attribute.self, from: data) as! Array<Attribute> 

First error I get is this:

Cast from 'Attribute' to unrelated type 'Array< Attribute>' always fails

If I remove the cast part I catch this error when the decode tries...

Optional("The data isn’t in the correct format.")

Any ideas?

Upvotes: 0

Views: 1305

Answers (1)

David Pasztor
David Pasztor

Reputation: 54755

You need to pass in the array to decode, don't pass in the array element type, then try to force-cast that to an array, that doesn't make any sense. YourType and Array<YourType> are two different and completely unrelated types, so you cannot cast one to the other and you need to use the specific type when calling JSONDecoder.decode(_:from:).

let array = try JSONDecoder().decode([Attribute].self, from: data)

Btw as already pointed out in your previous question, there is no need to manually write the init(from:) and encode(to:) methods or the CodingKeys enum since for your simple type, the compiler can auto-synthesise all of those for you. Also, if you used a struct instead of class, you'd also get the member wise initialiser for free.

Upvotes: 2

Related Questions