一、问题

  1. 对于运用HandyJsonCodable来解析的数据转成Realm实例时失利!!!
  2. 转成Realm实例时HandyJson自定义映射无效!!!

二、解决方案

1. HandyJson

问题1:
let JsonString = """
{"genres":[{"id":28,"name":"Action"},{"id":12,"name":"Adventure"},{"id":16,"name":"Animation"},{"id":35,"name":"Comedy"},{"id":80,"name":"Crime"},{"id":99,"name":"Documentary"}]}
"""
class Genres: Object, HandyJSON {
    @objc dynamic var id: String = ""
    @objc dynamic var name: String?
    override class func primaryKey() -> String? {
        "id"
    }
    override required init() {
        super.init()
    }
}
let list: [Genres] = ([Genres].deserialize(from: JsonString, designatedPath: "genres") ?? []).compactMap { $0 }
list.forEach { print($0.id, $0.name) }

这儿Realm对象的特点不可运用@Persisted标示,应该运用@objc dynamic标示为OC的动态类型。运用HandyJson有个便捷之处是解析时能够直接将idInt转成String

问题2:

这儿有两种解决思路,直接上代码:

let JsonString = """
{"genres":[{"id":28,"name":"Action"},{"id":12,"name":"Adventure"},{"id":16,"name":"Animation"},{"id":35,"title":"Comedy"},{"id":80,"title":"Crime"},{"id":99,"title":"Documentary"}]}
"""
class Genres: Object, HandyJSON {
    @objc dynamic var id: String = ""
    @objc dynamic var name: String?
    private var title: String?
    override class func primaryKey() -> String? {
        "id"
    }
    override required init() {
        super.init()
    }
    /// 转换完成后赋值
    func didFinishMapping() {
        name = [name, title].compactMap { $0 }.first
    }
}
let list: [Genres] = ([Genres].deserialize(from: JsonString, designatedPath: "genres") ?? []).compactMap { $0 }
list.forEach { print($0.id, $0.name) }

这种方法是在HandyJsondidFinishMapping中直接给特点赋值。再看另一种方法:

let JsonString = """
{"genres":[{"id":28,"name":"Action"},{"id":12,"name":"Adventure"},{"id":16,"name":"Animation"},{"id":35,"title":"Comedy"},{"id":80,"title":"Crime"},{"id":99,"title":"Documentary"}]}
"""
class Genres: Object, HandyJSON {
    @objc dynamic var id: String = ""
    @objc dynamic var name: String?
    @objc private var title: String? {
        willSet {
            name = newValue
        }
    }
    override class func ignoredProperties() -> [String] {
        ["title"]
    }
    override class func primaryKey() -> String? {
        "id"
    }
    override required init() {
        super.init()
    }
}
let list: [Genres] = ([Genres].deserialize(from: JsonString, designatedPath: "genres") ?? []).compactMap { $0 }
list.forEach { print($0.id, $0.name) }

这儿需求留意title特点前面加了@objc润饰表示这是OC特点,这样HandyJson在对title赋值时willSet将被调起,咱们能够在willSet中对name进行赋值。假如不希望title特点也存储到Realm中,能够在RealmignoredProperties方法中标示。

执行代码后能够验证成果:

Realm结合HandyJSON或Codable的坑

Realm的表结构能够看出,只要idnametitle并不存在,其次name的值也是完好的,这也符合咱们的预期。

2. Codable

let JsonString = """
{"genres":[{"id":28,"name":"Action"},{"id":12,"name":"Adventure"},{"id":16,"name":"Animation"},{"id":35,"name":"Comedy"},{"id":80,"name":"Crime"},{"id":99,"name":"Documentary"}]}
"""
class GenresModel: Object, Codable {
    @Persisted(primaryKey: true) var id: Int
    @Persisted var name: String?
    override required init() {
        super.init()
    }
}
let list = ([GenresModel].decodeJSON(from: JsonString, designatedPath: "genres") ?? []).compactMap { $0 }
list.forEach { print($0.id, $0.name) }

这儿Realm对象的特点能够运用@Persisted标示。运用Codable解析时需求留意匹配数据类型,不能够直接将idInt转成String,当然你也能够写映射方法来完成。