我想在Swift中表示一个通用的JSON对象:
let foo: [String: Any] = [
"foo": 1,
"bar": "baz",
]
Run Code Online (Sandbox Code Playgroud)
但[String: Any]编译器建议的类型并不能很好地工作.我无法检查该类型的两个实例是否相等,例如,虽然这应该可以使用两个JSON树.
什么也行不通的是使用Codable机器将该值编码为JSON字符串:
let encoded = try JSONEncoder().encode(foo)
Run Code Online (Sandbox Code Playgroud)
哪个因错误而爆炸:
fatal error: Dictionary<String, Any> does not conform to Encodable because Any does not conform to Encodable.
Run Code Online (Sandbox Code Playgroud)
我知道我可以引入一个精确的类型,但我遵循通用的JSON结构.我甚至尝试为泛型JSON引入一种特定类型:
enum JSON {
case string(String)
case number(Float)
case object([String:JSON])
case array([JSON])
case bool(Bool)
case null
}
Run Code Online (Sandbox Code Playgroud)
但是当实现Codable这个枚举时我不知道如何实现encode(to:),因为一个键控容器(用于编码对象)需要一个特定的CodingKey参数,我不知道如何得到它.
是否真的不可能创建一个Equatable通用的JSON树并使用它编码Codable?
为什么名称 Array 没有解码?
为 Playground 做好准备,简单地将其粘贴到您的 Playground 中
import Foundation
struct Country : Decodable {
enum CodingKeys : String, CodingKey {
case names
}
var names : [String]?
}
extension Country {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
names = try values.decode([String]?.self, forKey: .names)!
}
}
let json = """
[{
"names":
[
"Andorre",
"Andorra",
"????"
]
},{
"names":
[
"United Arab Emirates",
"Vereinigte Arabische Emirate",
"Émirats Arabes Unis",
"Emiratos Árabes Unidos",
"????????",
"Verenigde …Run Code Online (Sandbox Code Playgroud) 我有一个符合协议EmailVerificationStatus的关联类型的枚举:StringCodable
enum EmailVerificationStatus: String, Codable {
case unverified
case verified
}
Run Code Online (Sandbox Code Playgroud)
我正在使用的网络服务以大写 ( UNVERIFIED/ VERIFIED)发送这些案例。我如何使用CodingKeys枚举来映射这种差异?类似以下内容不起作用:
enum CodingKeys: String, CodingKey {
case unverified = "UNVERIFIED"
case verified = "VERIFIED"
}
Run Code Online (Sandbox Code Playgroud) 考虑以下对象:
struct User: Codable {
let id: Int
let email: String
let name: String
}
Run Code Online (Sandbox Code Playgroud)
是否有可能获得CodingKey给定的特定信息KeyPath?
let key = \User.name.codingKey // would be equal to string: "name"
Run Code Online (Sandbox Code Playgroud) 我正在使用PINCache将缓存添加到我的应用中,并且处于缓存系统调用编码/解码的委托方法的情况。这些方法是通用的,但通用值未明确符合Codable。因为它们是委托,所以我无法更改签名以使泛型类型符合Codable。
func modelForKey<T : SimpleModel>(_ cacheKey: String?, context: Any?, completion: @escaping (T?, NSError?) -> ()) {
guard let cacheKey = cacheKey, let data = cache.object(forKey: cacheKey) as? Data, T.self is Codable else {
completion(nil, nil)
return
}
let decoder = JSONDecoder()
do {
let model: T = try decoder.decode(T.self, from: data)
completion(model, nil)
} catch {
completion(nil, nil)
}
}
Run Code Online (Sandbox Code Playgroud)
使用此代码,我遇到以下错误:
在参数类型中
T.Type,T与预期类型不符Decodable
如何强迫我decoder接受通用价值?
我有一个Codable结构,用于解码传入的JSON.不幸的是,有时它的一个键的值是一个字符串,有时它是一个浮点数.我能够在下面拼凑一些do/try/catch块以使其工作,但是有更好的方法来处理它吗?
struct Project: Codable {
public let version: Float
init(from decoder: Decoder) throws {
var decodedVersion: Float = 1.0
do {
decodedVersion = try values.decode(Float.self, forKey: .version)
} catch {
do {
if let inVersion = try Float(values.decode(String.self, forKey: .version)) {
decodedVersion = inVersion
}
} catch {
throw error
}
}
version = decodedVersion
}
}
Run Code Online (Sandbox Code Playgroud) 我需要添加Codable两个类。一是CLLocationCoordinate2D,二是CLCircularRegion。
我对此没有任何问题CLLocationCoordinate2D,并且可以通过这样做来实现:
extension CLLocationCoordinate2D: Codable {
public enum CodingKeys: String, CodingKey {
case latitude
case longitude
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(latitude, forKey: .latitude)
try container.encode(longitude, forKey: .longitude)
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
latitude = try values.decode(Double.self, forKey: .latitude)
longitude = try values.decode(Double.self, forKey: .longitude)
}
}
Run Code Online (Sandbox Code Playgroud)
但我在尝试做同样的事情时遇到了很多问题CLCircularRegion。由于radius和center是只读属性,我无法真正以相同的方式创建它们。另一个问题是为什么我能够创建public …
无法理解为什么我的类不符合Codable请不要在我的情况下我不需要实现编码和解码方法.
public class LCLAdvantagePlusJackpotCache: Codable {
public let token: String
public let amount: NSNumber
public let member: Bool
public init(token: String, amount: NSNumber, member: Bool) {
self.token = token
self.amount = amount
self.member = member
}
enum CodingKeys: String, CodingKey {
case token, amount, member
}
}
Run Code Online (Sandbox Code Playgroud) 我希望在这里能理解此错误,并且可能对可编码和可解码的内容有更广泛的了解。我班的一部分看起来如下:
public var eventId: String?
public var eventName: String?
public var eventDescription: String?
public var location: CLLocation?
/// These properties will be encoded/decoded from JSON
private enum CodingKeys: String, CodingKey {
case eventId
case eventName
case eventDescription
case location
}
public required convenience init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let eventId = try container.decode(String?.self, forKey: .eventId)
let eventName = try container.decode(String?.self, forKey: .eventName)
let location = try container.decode(CLLocation?.self, forKey: .location)
self.init(eventId: eventId, eventName: eventName, location:location) …Run Code Online (Sandbox Code Playgroud) 我试图解码一个json文件,并且我在那里有很多ui配置,我正在寻找一个干净的解决方案以直接将十六进制代码解析为UIColor。但是UIColor不符合Codable。
例如这个json:
var json = """
{
"color": "#ffb80c"
}
""".data(using: .utf8)!
Run Code Online (Sandbox Code Playgroud)
我希望能够做到这一点:
struct Settings: Decodable {
var color: UIColor
}
Run Code Online (Sandbox Code Playgroud)
并且即时解码时将“ hex”字符串转换为UIColor
我已经有了此函数来从String解码并返回UIColor:
public extension KeyedDecodingContainer {
public func decode(_ type: UIColor.Type, forKey key: Key) throws -> UIColor {
let colorHexString = try self.decode(String.self, forKey: key)
let color = UIColor(hexString: colorHexString)
return color
}
}
Run Code Online (Sandbox Code Playgroud)
为此,我需要通过获取容器并对其进行解码来对其进行手动解码,但是由于我有很多配置,因此我的课程非常庞大,因为我需要设置所有内容:
struct Settings: Decodable {
var color: Color
enum CodingKeys: CodingKey {
case color
}
init(from decoder: Decoder) throws {
let container = try …Run Code Online (Sandbox Code Playgroud)