这绝对是可能的,因为它是如何Foundation does it on Darwin:
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
let topLevel: Any
do {
topLevel = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
} catch {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
}
let decoder = __JSONDecoder(referencing: topLevel, options: self.options)
guard let value = try decoder.unbox(topLevel, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
}
您可以将任何内容传递给__JSONDecoder,它将对其进行解码.不幸的是,__JSONDecoder是私有的.但它也是开源的,所以这是可以修复的.太乏味了.
您需要复制大约1500 lines of __JSONDecoder implementation个和一些支持类型,删除__JSONDecoder前面的"Private",然后您可以添加一个可以执行您想要的扩展:
extension JSONDecoder {
fileprivate var options: _Options {
return _Options(dateDecodingStrategy: dateDecodingStrategy,
dataDecodingStrategy: dataDecodingStrategy,
nonConformingFloatDecodingStrategy: nonConformingFloatDecodingStrategy,
keyDecodingStrategy: keyDecodingStrategy,
userInfo: userInfo)
}
func decode<T : Decodable>(_ type: T.Type, from topLevel: Any) throws -> T {
let decoder = __JSONDecoder(referencing: topLevel, options: self.options)
guard let value = try decoder.unbox(topLevel, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
}
}
// And then it "just works":
let score = try JSONDecoder().decode(Score.self, from: scoreDictionary)