可编码:展平结构

时间:2019-03-21 03:00:09

标签: swift codable

假设我有某种具有JSON表示形式的类型,

{
  "count": 3,
  "name": "Pianos",
  "type": "instrument",
  "id": 1,
}

假设我想将其表示为如下所示的Swift对象:

struct SomeObject: Codable { // this is the object I'd like to represent
  let id: Int
  let details: SomeDetails
}

struct SomeDetails: Codable {
  let count: Int
  let name: String
  let type: String
}

毫无疑问地解码此对象。但是在这种情况下编码将如何工作,以便我可以编码为扁平结构-与我用来创建此对象并在上面的JSON示例中共享的结构相同?

3 个答案:

答案 0 :(得分:1)

  

但是在这种情况下编码将如何工作?

它可以正常工作:

struct SomeObject: Codable { 
    let id: Int
    let details: SomeDetails
}
struct SomeDetails: Codable {
    let count: Int
    let name: String
    let type: String
}
let someobject = SomeObject(id: 10, details: SomeDetails(count: 3, name: "ho", type: "hey"))
let json = try! JSONEncoder().encode(someobject)

如果您坚持要人为压平,只需编写自己的encode(to:),如下所示:

struct SomeObject: Codable {
    let id: Int
    let details: SomeDetails
    enum Keys : String, CodingKey {
        case id
        case count
        case name
        case type
    }
    func encode(to enc: Encoder) throws {
        var con = try enc.container(keyedBy: Keys.self)
        try con.encode(id, forKey: .id)
        try con.encode(details.count, forKey: .count)
        try con.encode(details.name, forKey: .name)
        try con.encode(details.type, forKey: .type)
    }
}
struct SomeDetails: Codable {
    let count: Int
    let name: String
    let type: String
}
let someobject = SomeObject(id: 10, details: SomeDetails(count: 3, name: "ho", type: "hey"))
let json = try! JSONEncoder().encode(someobject)

答案 1 :(得分:0)

如果将来有人在阅读(嗨!),这只是步入您的构造类型而将抽象值装箱的问题。

localhost:8480/assets/images/logo.png

答案 2 :(得分:0)

对先前答案的改进。无需手动编码或解码其他对象,您只需转发初始化程序即可。

struct SomeDetails: Codable {
  let count: Int
  let name: String
  let type: String
}

struct SomeObject: Codable {
  enum CodingKeys: String, CodingKey {
    case id
  }

  let id: Int
  let details: SomeDetails

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    id = try container.decode(Int.self, forKey: .id)
    details = try SomeDetails(from: decoder)
  }

  func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(id, forKey: .id)
    try details.encode(to: encoder)
  }
}

对于添加的糖,您可以使用Swift 5s动态成员查找,以便您可以很好地访问这些成员object.name

@dynamicMemberLookup
struct SomeObject {
  ...

  subscript<T>(dynamicMember member: KeyPath<SomeDetails, T>) -> T {
    details[keyPath: member]
  }
}