【问题标题】:Swift and Codable: Encodable tree struct terminating in values that obey custom protocolSwift 和 Codable:可编码树结构,以遵循自定义协议的值终止
【发布时间】:2019-04-15 15:03:06
【问题描述】:

我正在尝试使树数据结构遵循可编码协议。树终止于遵守协议“终端”的“某个对象”。终端扩展了 Codable。

树的每个节点都是一对。它有一个键和一个值。该值可以是一对,也可以是一个终端。

主要有两个问题:

1) 我希望这个结构能够编码为 JSON,这样

class Pair: Codable {
   var key: String?
   var value: Codable?
}

let outputSimple = Pair(key: "a test key", value: "a test value")
// encodes to
// {"a test key": "a test value"}
// whereas currently encodes to
// {}

let outputComplex = Pair(key: "a parent", value: Pair(key: "another pair", value: "a test value"))
// encodes to
// {"a parent": {"another pair", "a test value"}}

编辑:第 2 部分可能会稍微混淆这个问题。为了澄清上述问题,如果我有

class Pair: Codable {
   var key: String
   var value: String
}
let p = Pair(key:"foo", value: "bar")

我怎样才能让它输出 {"foo":"bar"} 而不是 {key:foo, value:bar}?我试过了

    override func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        container.encode(contentsOf: [key: value])
    }

但得到错误“实例方法'encode(contentsOf:)'要求'(key: _, value: _)'符合'Encodable'”

2) 我正在尝试以下操作,但它似乎不起作用。我得到“对不符合协议'Decodable'”

protocol TreeNode: Codable {} 
struct Pair: TreeNode {
   var key: String?
   var value: TreeNode?
}

extension String: TreeNode {}

我可以通过将 TreeNode 设为一个类和 Pair 一个子类来解决这个问题。这也可能是正确的 Swift 行为。但是,我想知道是否有更多双眼睛可以解释这个问题。我假设只要我确保所有值都是类型对,或者其他遵循 Codable 的类型,那么它就可以工作。

【问题讨论】:

  • 查看GenericJSON 以使用Codable 创建动态、类型安全的 JSON。您可以简化它以满足您对Tree/Pair 的需求。
  • 谢谢。这就是我正在采用的方法,但它涉及将终端节点包装在一个类中。该类的编码方法然后执行 GenericJSON 样式编码

标签: json swift parsing codable


【解决方案1】:

这行不通。

value 必须是符合Codable 的具体类型,而不是协议本身或符合Codable 的第二个协议

您可以做的是将value 声明为泛型

class Pair<T: Codable>: Codable {
    var key: String?
    var value: T?

    init(key: String?, value: T?) {
        self.key = key
        self.value = value
    }
}

它可以同时编码outputSimpleoutputComplex

【讨论】:

  • 我认为这是对第 2 部分的回答?第 1 部分仍将编码为 {"key": "foo", "value": "bar"} for Pair(key: "foo", value: "bar"}?
  • 其实这两个部分都有同样的问题:你不能使用Codable或者其他符合Codableprotocol作为类型。我会使用nil 作为终结者。
  • 不幸的是,为了简单起见,我在上面的讨论中遗漏了另一个数据结构“数组”。数组可以有任何可编码的对象,所以我不能在 Array 中指定 T 除了 Array 和 Any 不可编码/
  • 我可能把这个问题变成了一个两部分的问题。在第 1 部分中,现在假设 key 和 value 都是字符串,我需要制作一个字典 "{: }" 而不是标准的可编码 {"key": , "value ": }
  • T 也可以是数组,例如 [Pair],但所有项目必须具有相同的 value 类型。你根本无法编码Any
猜你喜欢
  • 2018-03-31
  • 2020-08-16
  • 2020-05-30
  • 2021-07-06
  • 2018-01-25
  • 1970-01-01
  • 2022-08-21
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多