Swift Codable - 如何对字符串类型的JSON值进行编码和解码?

4
我是一名有用的助手,为您翻译以下内容:

我与之交流的服务器期望以以下格式接收消息:

{
  "command": "subscribe",
  "identifier": "{\"channel\": \"UserChannel\"}",
  "data": "{\"key\": \"value\"}"
}

其中identifierdata值是转义后的JSON字符串。

到目前为止,我有:

struct ActionCableMessage<Message: Encodable>: Encodable {
    let command: Command
    let identifier: CableChannel
    let data: Message?

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

        try container.encode(identifier, forKey: .identifier) // ????
    }

    private enum CodingKeys: String, CodingKey {
        case command, identifier, data
    }
}

但是我不知道接下来该怎么做。我认为我需要一个协议,让CableChannelMessage都符合,并提供一个扩展函数来实现encode(to encoder: Encoder),确保Encoder必须是JSONEncoder,如果是,则使用它将自己的值重写为转义后的json字符串。

我还需要将其解码回ActionCableMessage结构体,但我还没有做到这一步。


https://developer.apple.com/swift/blog/?id=37 - Augusto
1个回答

2

我认为我需要一个CableChannel和Message都能符合的协议

好的,那个协议就是Encodable(如果你更喜欢,也可以是Codable)。

// just implement these as you normally would
extension CableChannel : Encodable { ... }
extension Message : Encodable { ... }

然后在 ActionCableMessage 中,您使用另一个编码器将内部对象编码为 JSON 数据,然后将其转换为字符串,再对该字符串进行编码:

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

    let subencoder = JSONEncoder()
    let identifierString = try String(data: subencoder.encode(identifier), encoding: .utf8)
    
    try container.encode(identifierString, forKey: .identifier)

    // do the same for "data"
}

同样地,对于解码:
init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    command = try container.decode(String.self, forKey: .command)
    let identifierJSONString = try container.decode(String.self, forKey: .identifier)
    // do the same for "data"
    
    let subdecoder = JSONDecoder()
    identifier = try subdecoder.decode(CableChannel.self, from: identifierJSONString.data(using: .utf8)!)
    // do the same for "data"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接