【问题标题】:Realm swift list using Decodable使用可解码的领域快速列表
【发布时间】:2017-09-14 18:41:31
【问题描述】:

我正在尝试弄清楚如何使用 Swift 4 中的新功能可解码协议来解析领域列表。

这是一个 JSON 示例:

  [{
     "name": "Jack",
     "lastName": "Sparrow",
     "number": "1",
     "address": [
        {
           "city": "New York",
           "street": "av. test"
        }
     ]
  },
  {
     "name": "Cody",
     "lastName": "Black",
     "number": "2"
  },
  {
     "name": "Name",
     "lastName": "LastName",
     "number": "4",
     "address": [
        {
           "city": "Berlin",
           "street": "av. test2"
        },
        {
           "city": "Minsk",
           "street": "av. test3"
        }
     ]
  }]

和领域模型:

人物

public final class Person: Object, Decodable {

    @objc dynamic var name = ""
    @objc dynamic var lastName = ""
    var address = List<Place>()

    override public static func primaryKey() -> String? {
        return "lastName"
    }

    private enum CodingKeys: String, CodingKey { case name, lastName, address}

    convenience public init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        self.lastName = try container.decode(String.self, forKey: .lastName)
        self.address = try container.decodeIfPresent(List<Place>.self, forKey: .address) ?? List()
    }
}

地点

public final class Place: Object, Decodable {

    @objc dynamic var city = ""
    @objc dynamic var street = 0

    override public static func primaryKey() -> String? {
        return "street"
    }
 // We dont need to implement coding keys becouse there is nothing optional and the model is not expanded by extra properties.   
}

解析这个 JSON 的结果是:

[Person {
    name = Jack;
    lastName = Sparrow;
    number = 1;
    address = List<Place> <0x6080002496c0> (

    );
}, Person {
    name = Cody;
    lastName = Black;
    number = 2;
    address = List<Place> <0x6080002496c0> (

    );
}, Person {
    name = Name;
    lastName = LastName;
    number = 4;
    address = List<Place> <0x6080002496c0> (

    );

我们可以看到我们的列表总是空的。

self.address = try container.decodeIfPresent(List<Place>.self, forKey: .address) ?? List()

将永远是nil

我还将List 扩展为:

extension List: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
    }
}

有什么想法可能是错的吗?

编辑

struct LoginJSON: Decodable {
    let token: String
    let firstCustomArrayOfObjects: [FirstCustomArrayOfObjects]
    let secondCustomArrayOfObjects: [SecondCustomArrayOfObjects]
    let preferences: Preferences
    let person: [Person]
}

每个属性(而不是令牌)都是Realm Object 的类型,最后一个是上面的那个。

谢谢!

【问题讨论】:

  • @matt 是的,没错。它是RealmSwift.List
  • @matt 是的,这是自定义的 Realm 类型。 Here 的文档
  • @matt 我无法将其解析为 Realm 模型类中的数组,我必须将其解析为 Realm 对象才能将其保存到 db 中而无需在代码中进行冗余操作;x跨度>
  • @matt 在 swift 4 中你不需要 JSONDecoder,这就是你现在解析 JSON 所需要的:D
  • @matt 哦,对不起。我忘记了。我的 JSON 更复杂,我刚刚发布了一个示例,指出问题所在。基本上我的结构很少有对象(对象数组很少)。 let parsedJson = try! JSONDecoder().decode(MyStructure.self, from: data) -data 是来自 Alamofire 的 DataResponse&lt;Data&gt;。这是解析 json medium.com/swiftly-swift/… 数组的来源 - 这就是为什么我说我在里面有 Realm 对象的结构。

标签: swift realm decodable


【解决方案1】:

您不能直接从 JSON 转到列表。 JSON 中的内容是一个数组。所以这条线行不通:

self.address = try container.decodeIfPresent(List<Place>.self, forKey: .address) ?? List()

你必须从获取数组开始:

if let arr = try container.decodeIfPresent(Array<Place>.self, forKey: .address) {
    // arr is now an array of Place
    self.address = // make a List from `arr`, however one does that
} else {
    self.address = nil
}

【讨论】:

  • 如何将 Array 类型转换为 List 类型?它不会让我通过as。谢谢!解决了我的问题。
  • 我不知道。我对Realm一无所知。您必须阅读 Realm 文档。我创建了自己的 List 泛型类型并提供了一种方法来执行此操作,并且我能够很好地解码您的 JSON。
  • 我已经制定了一个解决方案,只需使用 foreach !再次感谢!
  • @Derp 我遇到了同样的问题,我按照 matt 说的做了,但是同样的问题列表将包含 nil 你能分享将数组类型转换为列表类型吗?
  • @Basil 请不要在 cmets 上窃取这个。如果您有问题,我建议您将其作为一个问题!这样,您就可以提出整个问题并获得一些实际帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
相关资源
最近更新 更多