I want to Do:
JSONDecoder()
, I convert json
to Realm
object.Realm
databases.Problem:
RLMArray
don't apply Codable
protocol.Decodable
protocol, but Codable
I couldn't.Error Message:
Code:
public class Hobby: Object, Codable {
@objc dynamic var title: String?
@objc dynamic var category: String?
}
public class Person: Object, Codable { // Error: Type 'Person' does not conform to protocol 'Encodable'
@objc dynamic var name: String?
@objc dynamic var hobbies: RLMArray<Hobby>?
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
hobbies = try container.decode(RLMArray<Hobby>?.self, forKey: .hobbies)
}
}
func sample() {
let person = try? JSONDecoder().decode(Person.self, from: "{\"name\" : \"aaa\",\"hobbies\" : [{\"title\" : \"fishing\",\"category\" : \"outdoor\"},{\"title\" : \"reading\",\"type\" : \"indoor\"}]}".data(using: .utf8)!)
print(person)
let realm = try! Realm()
try! realm.write {
realm.add(person!)
}
}
Do you have some ideas?
Swift4 RealmSwift
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