设想一个如下的数据结构,其中包含一个contents格式的值,它是一个已经编码的JSON片段。
let partial = """
{ "foo": "Foo", "bar": 1 }
"""
struct Document {
let contents: String
let other: [String: Int]
}
let doc = Document(contents: partial, other: ["foo": 1])期望输出
组合数据结构应该按原样使用contents并对other进行编码。
{
"contents": { "foo": "Foo", "bar": 1 },
"other": { "foo": 1 }
}使用Encodable
下面的Encodable实现将Document编码为JSON,但是它也将contents重新编码为字符串,这意味着它包含在引号中,并将所有"引号转义为\"。
extension Document : Encodable {
enum CodingKeys : String, CodingKey {
case contents
case other
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(contents, forKey: .contents)
try container.encode(other, forKey: .other)
}
}输出
{
"contents": "{\"foo\": \"Foo\", \"bar\": 1}",
"other": { "foo": 1 }
}encode如何按原样通过contents?
发布于 2020-10-28 04:35:12
我可能会晚一点,但我希望这对未来的人有帮助。我遇到过类似的问题,我有一些预编码的变量,并希望将它们嵌套在某个可编码的父结构中。
struct Request: Encodable {
let variables: [String: Data] // I'd encode data to JSON someplace else.
}不幸的是,每个键值的类型是不同的(例如,你可以在一个键中有一个整数,在另一个键中有一个对象),并且我不能从我第一次编码它的地方向上传递信息。下面是我的想法:
{
"variables": {
"one": { "hello": "world" },
"two": 2
}
}枚举和泛型也不是一个选择,因为这是一个高度灵活的部分,只需要类型符合Encodable。
总而言之,我最终复制了您可以找到here的大部分Swift的JSONEncoder实现。(我建议清理JSONDecoder实现,因为它在我们的例子中没有用处。)
需要更改的部分在JSONEncoder类的encode函数中。基本上,您希望将获取topLevel值的部分(即NSObject)和序列化它的部分分开。新的encode还应该返回NSObject-type,而不是Data。
open func encode<T : Encodable>(_ value: T) throws -> NSObject {
let encoder = __JSONEncoder(options: self.options)
guard let topLevel = try encoder.box_(value) else {
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) did not encode any values."))
}
return topLevel
}一旦你有了它,你就可以将JSON作为一个类型来传递,剩下的重要一步就是你运行JSONSerialization.data函数来获得实际的NSObject。JSONEncoder在内部所做的是将Encodable结构简化为Foundation类型。然后,JSONSerialization可以处理这些类型,您将获得一个有效的JSON。
下面是我如何使用它的:
let body: Any = [
"query": query, // String
"variables": variables // NSObject dictionary
]
let httpBody = try! JSONSerialization.data(
withJSONObject: body,
options: JSONSerialization.WritingOptions()
)
request.httpBody = httpBodyhttps://stackoverflow.com/questions/58175721
复制相似问题