json - Swift Codable - 如何编码和解码字符串化的 JSON 值?
问题描述
我正在与之交谈的服务器需要以下格式的消息:
{
"command": "subscribe",
"identifier": "{\"channel\": \"UserChannel\"}",
"data": "{\"key\": \"value\"}"
}
其中identifier
和data
值是转义的 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
}
}
但我不知道从这里做什么。我认为我需要一个protocol
thatCableChannel
并且Message
可以符合提供extension
的实现 func的函数encode (to encoder: Encoder)
,它确保Encoder
必须是 a JSONEncoder
,如果是这样,则使用它将它自己的值重写为转义的 json 字符串。
我还需要将其解码回ActionCableMessage
结构,但我还没有走那么远。
解决方案
我想我需要一个 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"
}
推荐阅读
- apache-spark - 在一个数据框中获取两列之间的 Jaccard 相似度
- android - 如何将值从 volley 的 onResponse() 存储到静态变量中
- java - 如果显示 recyclerView,如何停止显示加载?
- ios - 带有过滤器、feGaussianBlur 和 feColorMatrix 的 iOS/safari 上的 SVG 凸起
- windows-10 - Terraform 在为插件指定的目录中找不到第三方插件
- r - 如何将字符向量转换为变量名和str_count?
- javascript - $(...).mask 不是一个函数,具体取决于它被调用的位置
- c# - 如何在 C# 中启用在图片框上绘图
- c - getrusage 的大部分字段应该为 0 吗?
- javascript - 我想在 js 中制作一个不和谐的音乐机器人