Swift Codable - 如何编码和解码字符串化的 JSON 值?

Posted

技术标签:

【中文标题】Swift Codable - 如何编码和解码字符串化的 JSON 值?【英文标题】:Swift Codable - how to encode and decode stringified JSON values? 【发布时间】:2019-09-04 19:00:32 【问题描述】:

我正在与之交谈的服务器需要以下格式的消息:


  "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 可以符合的protocol,并提供一个实现encode (to encoder: Encoder)extension func,它确保Encoder 必须是JSONEncoder,如果是这样,使用将它自己的值重写为转义的 json 字符串。

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

【问题讨论】:

developer.apple.com/swift/blog/?id=37 【参考方案1】:

我想我需要一个 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"

【讨论】:

以上是关于Swift Codable - 如何编码和解码字符串化的 JSON 值?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Codable 解码 JSON,然后填充我的 SwiftUI

如何在 swift 4 Codable 中手动解码数组?

Swift Codable 期望解码 Dictionary<String, Any> 但找到了一个字符串/数据

如何从 Swift Codable 中排除属性?

如何在 Core Data 中使用 swift 4 Codable?

如何在 Core Data 中使用 swift 4 Codable?