简体   繁体   English

Swift和Codable:以可遵循自定义协议的值终止的可编码树结构

[英]Swift and Codable: Encodable tree struct terminating in values that obey custom protocol

I am attempting to make a tree data structure obey the encodable protocol. 我试图使树数据结构服从可编码协议。 The tree terminates in "some object" that obeys the protocol "Terminal". 树终止于服务于“终端”协议的“某个对象”。 Terminal extends Codable. 终端扩展了Codable。

Each node of the tree is a pair. 树的每个节点都是一对。 It has a key, and a value. 它有一个键和一个值。 The value is either a pair, or a Terminal. 值可以是一对,也可以是终端。

There are two main issues: 有两个主要问题:

1) I would like this structure to encode to JSON such that 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"}}

EDIT: part 2 might be confusing the issue slightly. 编辑:第2部分可能会略微混淆问题。 To clarify issue above, if I had 为了澄清上面的问题,如果我有

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

how could I get it to output {"foo":"bar"} rather than {key:foo, value:bar}? 我怎么能输出{“foo”:“bar”}而不是{key:foo,value:bar}? I tried 我试过了

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

but get the error "Instance method 'encode(contentsOf:)' requires that '(key: _, value: _)' conform to 'Encodable'" 但得到错误“实例方法'编码(contentsOf :)'要求'(key:_,value:_)'符合'Encodable'”

2) I was attempting the following but it doesn't appear to work. 2)我正在尝试以下但它似乎不起作用。 I get "Pair does not conform to protocol 'Decodable'" 我得到“配对不符合协议'可解码'”

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

extension String: TreeNode {}

This one I can get around by making TreeNode a class with Pair a subclass. 我可以通过使TreeNode成为具有Pair子类的类来解决这个问题。 It's also likely this is correct Swift behaviour. 这也可能是正确的Swift行为。 However, I wondered if more pairs of eyes could explain the issue. 但是,我想知道是否有更多的眼睛可以解释这个问题。 I assumed that as long as I ensured all values are either of type pair, or something else that obeys Codable then it would work. 我假设只要我确保所有值都是类型对,或其他服从Codable的值,那么它就可以工作。

This cannot work. 这不行。

value must be a concrete type which conforms to Codable , not the protocol itself or a second protocol conforming to Codable value必须是符合Codable的具体类型,而不是协议本身或符合Codable的第二个协议

What you can do is to declare value as generic 你可以做的是将value声明为通用value

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

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

It can encode both outputSimple and outputComplex 它可以编码outputSimpleoutputComplex

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM